[RESOLVED] Write bytes to file at specified position.
Say I have 10 parts of a file. Each part is 10,000 bytes.
Now say I receive these parts out of order meaning I cannot simply just write them in order as I receive them, but I am able to detect what part it is.
If I received part 3 how would I write those bytes in the 20,000-30,000 byte section of a file?
Re: Write bytes to file at specified position.
Maybe you can create a stream and fill the 20000 first bytes with zeros or nulls, and after this add the 10000 bytes that you received...
Re: Write bytes to file at specified position.
So say I receive part 3.
I write part 2 and 3 with zeroes and part 3 with the actual data.
I then receive part 1, how would I just change the first 10,000 bytes? And when I receive part 2 how would I just change the 10,000-20,000 bytes?
Re: Write bytes to file at specified position.
I never tried to do that but something like:
VB.NET Code:
Dim st As New IO.MemoryStream(30000)
Dim byt(10000) As Byte
Dim strDataReceuved(10000) As Byte
st.Write(byt, 0, 10000) 'Bytes, Offset, NumBytes
st.Write(strDataReceuved, 10000, 10000)
...
Re: Write bytes to file at specified position.
Open a FileStream, Seek to the appropriate position, Write the data. E.g.
vb.net Code:
Const BLOCK_SIZE As Integer = 10000
Dim blockIndex As Integer '0 for first block, 1 for second, etc.
Dim data(BLOCK_SIZE - 1) As Byte
'Get data here.
Using fs = IO.File.OpenWrite("file path here")
fs.Seek(blockIndex * BLOCK_SIZE, IO.SeekOrigin.Begin)
fs.Write(data, 0, BLOCK_SIZE)
End Using
Re: Write bytes to file at specified position.
Well this is a delayed response, but thanks for the help.
What am I doing wrong? I have purposely done the thread waits to simulate an out of order arrival.
vbnet Code:
'fnnn is a temp global filestream that is for the file I am writing to
Using fs = File.OpenRead(filePath)
If fs.CanRead Then
Do Until totalRead = fs.Length
read = fs.Read(buffer, 0, BYTES_TO_READ)
' sc.SendFile(uploadID, totalRead, read, buffer)
Dim t As New test
t.seek = totalRead
t.amount = read
t.data = buffer
Dim t22 As New Thread(AddressOf t.send)
t22.IsBackground = True
t22.Start()
totalRead += read
Loop
End If
End Using
Public Class test
Public seek As Integer
Public amount As Integer
Public data() As Byte
Public Sub send()
Dim r As New Random
Thread.Sleep(r.Next(100, 2000))
SyncLock fnnn
fnnn.Seek(seek, IO.SeekOrigin.Begin)
fnnn.Write(data, 0, amount)
End SyncLock
End Sub
End Class
The above only works if the pieces of the file arrive in order. The file size mimics correctly but it is is corrupted.
Re: Write bytes to file at specified position.
Are you saying that if you send one file, and then write that to the file, it doesn't work if the pieces don't arrive in order...
If that it's normal if you don't have anything that tells what piece belong to which position... but at beginning of the thread you said "I am able to detect what part it is", so what's the problem?
You have two options, use an auxiliar
Re: Write bytes to file at specified position.
Well I am asking why isn't the code I posted above not working. I am detecting where to start, how much I am writing and the data that is being wrote.
The problem is I am doing something wrong in it that is causing it to not work properly if it is out of order.
Re: Write bytes to file at specified position.
If you expect to be able to seek to any position in the file then you have to have created the file to its full size at the outset. For instance, lets say that you have a 2K file and you send it in two batches. How can you write the second kilobyte first if you don't know the file that size?
Re: Write bytes to file at specified position.
So using the same code I have above I have just added this to the file creation process.
I have tried this:
vbnet Code:
Dim fff As New FileInfo(fp)
fnnn = File.Create("C:\" & fn, fff.Length)
and this, but still no success.
vbnet Code:
Dim fff As New FileInfo(fp)
fnnn = File.Create("C:\" & fn)
Dim b(fff.Length) As Byte
fnnn.Write(b, 0, fff.Length)
Re: Write bytes to file at specified position.
Ok, I wrote up something small to just try to fix this problem alone.
This only works if each file part arrives in correct order. For example it works perfectly if I add a messagebox at the end of the loop or remove the threading.
I'm not sure what I am doing wrong.
This is the code I have:
vbnet Code:
Imports System.IO
Imports System.Threading
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ofd.ShowDialog() 'Open file dialog
start()
End Sub
Sub start()
Const BYTES_TO_READ As Integer = 10000 'Max bytes to be read at one time
Dim totalRead As Long = 0 'How many bytes have been read overall
Dim read As Long = 0 'The bytes read in one 'reading'
Dim buffer(BYTES_TO_READ - 1) As Byte 'Hold the bytes that are read
Dim nf As FileStream = File.Create("C:\test\" & ofd.SafeFileName) 'Create the new file
Using fs = File.OpenRead(ofd.FileName) 'Read through the file we are sending
FileWrite.total = fs.Length 'Get the file size of the file we want to copy
FileWrite.currentTotal = 0
Dim b(fs.Length) As Byte 'Create our initial file size for the new file
nf.Write(b, 0, fs.Length) 'Write empty bytes to the new file so it equals the old files length
Do Until totalRead = fs.Length 'Loop through the old file
read = fs.Read(buffer, 0, BYTES_TO_READ) 'Read 10,000 bytes at a time
Dim fw As New FileWrite(nf, totalRead, read, buffer) 'Initiate the filewrite class
Dim t As New Thread(AddressOf fw.start)
t.IsBackground = True
t.Start() 'Start multithreading for it
totalRead += read
Loop
End Using
End Sub
End Class
Class FileWrite
Public stream As FileStream 'Holds the stream to be writing to
Public seek As Long 'Where to seek to in the file stream
Public amount As Long 'How many bytes to write
Public data() As Byte 'The data to be written
Public Shared total As Long 'The file size of the file
Public Shared currentTotal As Long 'How much has already been written to the file
Sub New(ByVal fs As FileStream, ByVal SeekStart As Long, ByVal WriteAmount As Long, ByVal WriteData() As Byte)
stream = fs
seek = SeekStart
amount = WriteAmount
data = WriteData
End Sub
Sub start()
SyncLock stream 'So multiple threads don't access at the same time
stream.Seek(seek, SeekOrigin.Begin) 'Seek to the part of the file
stream.Write(data, 0, amount) 'Write to the file
currentTotal += amount 'Record how many bytes have been written
If currentTotal = total Then 'If all bytes have been written close the file
stream.Flush()
stream.Close()
End If
End SyncLock
End Sub
End Class
Re: Write bytes to file at specified position.
Maybe it's time to put some comments through your code so that you and others can quickly see what each part is intended to do, whether it actually does that and what parts may be missing.
Re: Write bytes to file at specified position.
Re: Write bytes to file at specified position.
Code:
'create file name and location
Dim dsktpDir As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim testFilePath As String = IO.Path.Combine(dsktpDir, "testfile.txt")
'open or create if it doesn't exist
Dim fsB As New FileStream(testFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)
'check the length
If fsB.Length < 10 * 10000 Then
fsB.SetLength(10 * 10000)
End If
'write two bytes
Dim abyte As Byte = 85 'U
fsB.Seek(99998, SeekOrigin.Begin)
fsB.WriteByte(abyte)
abyte = 90 'Z
fsB.WriteByte(abyte)
'check
fsB.Seek(99998, SeekOrigin.Begin)
abyte = CByte(fsB.ReadByte)
fsB.Flush()
fsB.Close()
Re: Write bytes to file at specified position.
I have found out the problem.
Since the data was stored in an array, when I passed the array to my sub class in a worker thread by the time it got to writing the data the array itself already had its data replaced with new bytes.
So the fix was as easy as:
data = WriteData
to
data = WriteData.Clone()
Thank you everyone for your help.