i am making an application which involves reading chunks of an existing file and writing them to a new one... now, the problem is that the code i am currently using does not create subfolders and then file if a full path is given...
If i give it a path like this: C:\folder1\folder2\file.mp3 it gives an error because the folders folder1 and 2 does not exist, however, i would like it to create these subfolders if they do not exist while creating the file... thanks... here is my code:
Dim bytesRead As Integer
Dim buffer(40096) As Byte
Using inFile As New System.IO.FileStream(arch, IO.FileMode.Open, IO.FileAccess.Read)
Using outFile As New System.IO.FileStream(path & "\" & f, IO.FileMode.Create, IO.FileAccess.Write)
inFile.Seek(StartAt, IO.SeekOrigin.Begin)
Do
If astop.Text = 1 = False Then
If CurrentFsize - currtotal < buffer.Length Then
ReDim buffer(CurrentFsize - currtotal)
End If
bytesRead = inFile.Read(buffer, 0, buffer.Length)
If bytesRead > 0 Then
outFile.Write(buffer, 0, bytesRead)
currtotal += bytesRead
End If
Else
Exit Do
Exit Do
End If
Application.DoEvents()
Loop While bytesRead > 0 AndAlso currtotal < CurrentFsize
End Using
End Using
Yout should create the directories and subdirectories of path before creating the output file:
If(Not System.IO.Directory.Exists(path)) Then
System.IO.Directory.CreateDirectory(path)
Related
What I'm trying to do:
Open two binary files, each 64 MB
Take first half of each byte of each file and combine those halves in 1 bytes same with second half, for example: first byte in first file is 0x51, in second file its 0xA2, so I need write two bytes in third file which are 0x5A and 0x12, same for whole bytes, therefore final length in third file will be 128 MB.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles
Button1.Click
Try
' choosing first file
OpenFileDialog1.FileName = "First file"
OpenFileDialog1.Title = "Choose the Address.bin file"
OpenFileDialog1.Filter = "bin files (*.bin)|*.bin|All files
(*.*)|*.*"
If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK
Then
Label1.Text =
System.IO.Path.GetFullPath(OpenFileDialog1.FileName)
Else
Exit Sub
End If
Catch ex As Exception
End Try
Try ' choosing first file
OpenFileDialog1.FileName = "Second FIle"
OpenFileDialog1.Title = "Choose the Flash.bin file"
OpenFileDialog1.Filter = "bin files (*.bin)|*.bin|All files (*.*)|*.*"
If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
Label2.Text = System.IO.Path.GetFullPath(OpenFileDialog1.FileName)
Else
Exit Sub
End If
Catch ex As Exception
End Try
Dim firstFileByte(1) As Byte
Dim SecondFileByte(1) As Byte
Dim Result As String
Dim Result2 As String
Dim Final(1) As Byte
For i = 0 To FileLen(Label1.Text) - 1
Using FirstFile As New FileStream(Label1.Text, FileMode.Open) 'save
'FIRST DIGIT********************************************************************************************
FirstFile.Seek(i, SeekOrigin.Begin)
FirstFile.Read(firstFileByte, 0, 1)
'TextBox1.Text = final(0).ToString("X")
Using SecFile As New FileStream(Label2.Text, FileMode.Open) 'save
SecFile.Seek(i, SeekOrigin.Begin)
SecFile.Read(SecondFileByte, 0, 1)
End Using
Result = firstFileByte(0).ToString("X2").Substring(0, 1) & SecondFileByte(0).ToString("X2").Substring(0, 1) ' comobining frist half of the first file and second file
Result2 = firstFileByte(0).ToString("X2").Substring(1, 1) & SecondFileByte(0).ToString("X2").Substring(1, 1) ' comobining second half of the first file and second file
End Using
Using vFs As New FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & "\Result.bin", FileMode.Append) ' save
TextBox1.Text = Result2
'Dim FileLenVar As UInt32 = FileLen(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & "\Result.bin") - 1
Final(0) = Convert.ToByte(Result, 16) 'converting result to the byte
Final(1) = Convert.ToByte(Result2, 16)
vFs.Write(Final, 0, 1)
vFs.Write(Final, 1, 1)
End Using
Next
End Sub
It works, but takes a lot of time: it writes 1 MB in 1 minute. How can I optimize it?
The files are small enough to load into RAM for processing. Processing the data in RAM can minimise the disk I/O needed, the latter very often being the slowest part of a program, especially if it is done in very small pieces like individual bytes. As also noted by Ben Voigt, string operations are somewhat slower than numeric operations.
Here's a simple demonstration of what could be done:
Imports System.IO
Module Module1
Dim f1 As String = "C:\temp\A.bin"
Dim f2 As String = "C:\temp\B.bin"
Dim outFile As String = "C:\temp\C.bin"
Sub CombineFiles()
Dim a1 = File.ReadAllBytes(f1)
Dim a2 = File.ReadAllBytes(f2)
Dim c(a1.Length + a2.Length - 1) As Byte ' c for combined
Dim highBits As Byte = &HF0
Dim lowBits As Byte = &HF
For i = 0 To c.Length - 1 Step 2
c(i) = a1(i \ 2) And highBits Or a2(i \ 2) >> 4
c(i + 1) = a1(i \ 2) << 4 Or a2(i \ 2) And lowBits
Next
File.WriteAllBytes(outFile, c)
End Sub
Sub CreateTestFiles()
'TODO: be more creative with the generated data.
Dim nBytes = 64
Dim a(nBytes - 1) As Byte
For i = 0 To nBytes - 1
a(i) = &H12
Next
File.WriteAllBytes(f1, a)
For i = 0 To nBytes - 1
a(i) = &HAB
Next
File.WriteAllBytes(f2, a)
End Sub
Sub Main()
'CreateTestFiles()
CombineFiles()
End Sub
End Module
Of course, you'd check that the input files were of equal length, and check for any other possible problems ;)
I've pulled a wave file from an online service I use and am now trying to save the returned stream. This is my code so far:
Using wavout = request.GetResponse.GetResponseStream
'error begins on next line
wavout.Seek(0, SeekOrigin.Begin)
Dim fs As FileStream = File.Create("output.wav")
Dim buf(65536) As Byte
Dim len As Integer = 0
While ((len = wavout.Read(buf, 0, 65536)) > 0)
fs.Write(buf, 0, len)
fs.Close()
End While
End Using
When I run the code it comes up with an exception saying 'this stream does not support seek operations'.
Can anyone see where I'm going wrong?
Some streams doesn’t support seeking. You can know it by a test such as “CanSeek”.
I’ve changed some lines in your code giving that as an answer to help you understanding the mechanism.
Dim request As Net.HttpWebRequest = CType(Net.WebRequest.Create("yoururlhere.com"), Net.HttpWebRequest)
Using wavout As IO.Stream = request.GetResponse().GetResponseStream()
'usnig this test you can avoid exceptions on seeking
If wavout.CanSeek Then
wavout.Seek(0, System.IO.SeekOrigin.Begin)
End If
Using fs As IO.FileStream = IO.File.Create("output.wav")
Dim buf(1024 * 8) As Byte
Dim len As Integer
Do
len = wavout.Read(buf, 0, buf.Length)
If len = 0 Then Exit Do
fs.Write(buf, 0, len)
Loop
End Using
End Using
I am reading a SSE by using this method
Public Shared Sub ReadStreamForever(ByVal stream As Stream)
Dim encoder = New UTF8Encoding()
Dim buffer = New Byte(2047) {}
Dim counter As Integer = 0
While True
If stream.CanRead Then
Dim len As Integer = stream.Read(buffer, 0, 2048)
counter = counter + 1
If len > 0 Then
Dim text = encoder.GetString(buffer, 0, len)
SSEApplication.Push(text) 'Here I collect the text slices to a List(of string) object
Else
Exit While
End If
Else
Exit While
End If
End While
SSEApplication.writer() 'Here I write the content to a .txt file
End Sub
With my example data it takes about 2 seconds. I would prefer not to read the stream into memory though and tried this method
Public Shared Sub ReadStreamForever1(ByVal stream As Stream)
Dim output As FileStream = File.OpenWrite("C:\Users\mini_dataset.txt")
While True
If stream.CanRead Then
stream.CopyTo(output)
Else
Exit While
End If
End While
End Sub
But the process ends up in an endless loop (I guess) at least to me it looks like the end of the stream can not be found. I can break the process after a few seconds and all the data are in the .txt file. Any idea what I can do to get the direct stream to file method working?
Stream.CanRead tells you whether a stream supports reading. Since it's apparently readable, While True will go on forever.
Let's verify whether the output Stream.CanWrite instead.
Public Shared Sub ReadStreamForever1(ByVal stream As Stream)
Using output As FileStream = File.OpenWrite("[Output file path]")
If output.CanWrite Then
stream.CopyTo(output)
End If
End Using
End Sub
If the process takes some time and you need to report its progress, you could read the stream using a buffer (I didn't add any error checking but of course a try/catch block should be used):
(Here, with 100 parts division commonly used by a ProgressBar)
Public Sub ReadStreamForever1(ByVal stream As Stream)
Dim BufferLength As Integer = 81920 'As the default stream buffer
Dim Buffer(BufferLength) As Byte
Dim BytesRead As Long = 0L
Using output As FileStream = File.OpenWrite("[Output file path]")
If output.CanWrite Then
Dim Part As Long = stream.Length \ 100
Dim PartCount As Integer = 0
Dim read As Integer = 0
Do
read = stream.Read(Buffer, 0, BufferLength)
If read = 0 Then Exit Do
If (BytesRead / Part > PartCount) Then
PartCount += 1
'ReportWriteProgress(PartCount)
End If
output.Write(Buffer, 0, read)
BytesRead += read
Loop
End If
End Using
End Sub
I use VB.net 2008 to make a memory scanner and hacking program. I try some of their answers but still the memory scanner is slow. Maybe I have an improvement because before I scan a simple minesweeper and it takes 10 to 20 minutes. But now I can scan it for 2 to 10 seconds.
But I'm still not satisfied because when I try it in other games it takes 5 to 10 minutes or sometimes freeze due of too much long and too much usage of CPU.
Here is my code
Assume I declare all the API and some arguments for making a first scan
this code is a sample of scanning a 4 bytes address:
'' Command Button Event
btn_firstScan(....) Handle....
'' The Code
Me.Enabled = False
FirstScanThread = New Thread(AddressOf scanF)
FirstScanThread.IsBackground = True
FirstScanThread.Priority = ThreadPriority.Highest
FirstScanThread.Start() '' Thread Started for the First Scan.
End sub
Private Sub scanF() '' This is the Function is being Executed by the FirstScanThread at the btn_firstScan.
FirstScan(Of Int32)(pHandle, &H400000, &H7FFF0000, CType(txt_value.Text, Int32))
End Sub
The Sub FirstScan Executed by Sub scanF() that is being Executed by FirstScanThread in Command button btn_firstScan sub
Friend Sub FirstScan(Of T)(ByVal pHandle As IntPtr, ByVal minAddress As Int64, ByVal maxAddress As Int64, _
ByVal VALUE As T, Optional ByVal tempFileName As String = "temp.txt")
Dim thr As New Thread(AddressOf getProcessMemoryInfo) '' Get the Process Memory Info First
Dim memRange As New scanRange
memRange.minimum_address = minAddress
memRange.maximum_address = maxAddress
thr.IsBackground = True
thr.Priority = ThreadPriority.Highest
thr.Start(memRange)
thr.Join()
thr = New Thread(AddressOf dumpReadProcessMemory) '' Read All Bytes and Dump to the Temporary File
thr.IsBackground = True
thr.Priority = ThreadPriority.Highest
thr.Start()
thr.Join()
thr = New Thread(AddressOf readTempFile) '' Scan the Dump File in a Specific Set of Bytes [4 Bytes Aligned]
thr.IsBackground = True
thr.Priority = ThreadPriority.Highest
thr.Start(VALUE)
thr.Join()
setControlState(Me, True) '' If the Scan is Complete , The form is Ready Again to Receive Input
End Sub
Friend Sub dumpReadProcessMemory() '' This Sub is Use to Dump the All Bytes Read by ReadProcessMemory
Dim INFO As FileStream = New FileStream("FIRST.INFO.txt", FileMode.Open, FileAccess.Read, FileShare.Read)
Dim SR As StreamReader = New StreamReader(INFO) '' This is use to Obtain the Info that is needed to switch Page by Page Faster , No need to obtain in VirtualQueryEx
Dim BFILE As FileStream = New FileStream("FIRST.SCAN.txt", FileMode.Create, FileAccess.Write, FileShare.Write)
Dim BW As BinaryWriter = New BinaryWriter(BFILE) '' This is the Binary Writer for writing the READ Bytes
Dim BUFFER(0 To (1048576 * 128)) As Byte
Dim mem As New memoryInfo
While Not SR.EndOfStream '' While there is Page Found
mem.regionBaseAddress = CLng(SR.ReadLine.ToString)
mem.regionSize = CLng(SR.ReadLine.ToString)
ReadProcessMemory(pHandle, mem.regionBaseAddress, BUFFER, mem.regionSize, 0)
BW.Write(BUFFER, 0, mem.regionSize)
Thread.Sleep(1)
End While
SR.Close()
SR.Dispose()
INFO.Close()
INFO.Dispose()
BW.Close()
BFILE.Close()
BFILE.Dispose()
GC.Collect() '' Collect Garbage of BUFFER prevent CPU Stressing and RAM Leak, and i think i helps :P
End Sub
Friend Sub getProcessMemoryInfo(ByVal Obj As Object) '' Use to Get What PAGE is Readable/Writable and its Size
Dim FILE As System.IO.FileStream = New System.IO.FileStream("FIRST.INFO.txt", IO.FileMode.Create, FileAccess.Write, IO.FileShare.Write)
Dim SW As System.IO.StreamWriter = New System.IO.StreamWriter(FILE)
Dim BASE_ADDRESS As Int64 = CLng(Obj.minimum_address.ToString)
Dim MAX As Int64 = CLng(Obj.maximum_address.ToString)
Dim PAGE_COUNT As Integer = 0
While VirtualQueryEx(pHandle, BASE_ADDRESS, MBI, MBIsize)
If MBI.State = MemoryAllocationState.Commit Then
If MBI.zType = MemoryAllocationType.MEM_PRIVATE Or MBI.zType = MemoryAllocationType.MEM_IMAGE Then
Select Case MBI.AllocationProtect
'' Check if The Region is Readable/Writable and Executable
Case MemoryAllocationProtectionType.PAGE_CANWRITE
GoTo WRITE_INFO
Case MemoryAllocationProtectionType.PAGE_EXECUTE_READWRITE
GoTo WRITE_INFO
Case MemoryAllocationProtectionType.PAGE_WRITECOMBINE
GoTo WRITE_INFO
Case MemoryAllocationProtectionType.PAGE_EXECUTE_WRITECOPY
GoTo WRITE_INFO
Case MemoryAllocationProtectionType.PAGE_READWRITE
GoTo WRITE_INFO
Case Else
GoTo BYPASS_WRITE
End Select
WRITE_INFO:
SW.WriteLine(BASE_ADDRESS)
SW.WriteLine(MBI.RegionSize.ToInt32)
Thread.Sleep(1)
'PAGE_COUNT += 1
End If
End If
BYPASS_WRITE:
BASE_ADDRESS = BASE_ADDRESS + MBI.RegionSize.ToInt32
updateProgressTo(Me.pb_scanProgress, CInt(BASE_ADDRESS / MAX * 100))
End While
SW.Close()
SW.Dispose()
FILE.Close()
FILE.Close()
'Console.WriteLine(PAGE_COUNT)
End Sub
Public Sub readTempFile(ByVal Value As Object)
Dim TEMP As System.IO.FileStream = New System.IO.FileStream("TEMP.txt", IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.Write)
Dim TFILE As System.IO.FileStream = New System.IO.FileStream("FIRST.INFO.txt", IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Dim BFILE As System.IO.FileStream = New System.IO.FileStream("FIRST.SCAN.txt", IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Dim SW As System.IO.StreamWriter = New System.IO.StreamWriter(TEMP) '' Will Contain a list of Addressed found with the Value input.
Dim SR As System.IO.StreamReader = New System.IO.StreamReader(TFILE) '' Contains the Region baseAddesses and Size
Dim BR As System.IO.BinaryReader = New System.IO.BinaryReader(BFILE) '' Contains the Bytes being Dump Before and will now Read for Scanning.
Dim ADDRESS_POINTER As Int64 = 0
Dim mem As New memoryInfo
Dim TEMP_BYTE(0 To 4 - 1) As Byte
Dim BUFFER(0 To (1024 * 1024)) As Byte = 1024KB
Dim BUFFER_INDEX = 0
mem.regionBaseAddress = CLng(SR.ReadLine.ToString) ''Obtain the Staring Base Address
mem.regionSize = CLng(SR.ReadLine.ToString) '' Obtain the Region Size
ADDRESS_POINTER = mem.regionBaseAddress
While BR.Read(BUFFER, 0, BUFFER.Length) '' Fill the BUFFER with Data
BUFFER_INDEX = 0
While BUFFER_INDEX < BUFFER.Length - (4 - 1)
For a As Integer = 0 To (4 - 1) '' Compile the Read Bytes
TEMP_BYTE(a) = BUFFER(BUFFER_INDEX + a)
Next
If BitConverter.ToInt32(TEMP_BYTE, 0) = Value Then '' If the Compiled 4 Bytes = Value then
SW.WriteLine(formatHex(Hex(ADDRESS_POINTER).ToString))
'addItemTo(Me.lb_addressList, formatHex(Hex(ADDRESS_POINTER).ToString))
End If
ADDRESS_POINTER += 4
BUFFER_INDEX += 1
mem.regionSize -= 4
If mem.regionSize <= 0 Then
If SR.EndOfStream Then
Exit While
Else
''Switch to the Next Region
mem.regionBaseAddress = CLng(SR.ReadLine.ToString) ''Obtain the Staring Base Address
mem.regionSize = CLng(SR.ReadLine.ToString) '' Obtain the Region Size
ADDRESS_POINTER = mem.regionBaseAddress
End If
End If
End While
Thread.Sleep(1) '' Prevent 100% CPU Usage therefore the Form and other App avoid Crashing and Not Responding,
End While
BR.Close()
BFILE.Close()
SW.Close()
TEMP.Close()
SW.Dispose()
TEMP.Dispose()
SR.Close()
SR.Dispose()
TFILE.Dispose()
GC.Collect()
setControlState(Me, True) '' Make the Form Enabled
End Sub
NOTE: formatHex is only a Function that will put trailing Zeros in the front of Hex String if the Hex is not have Length of 8.
This code works in minesweeper in Windows XP 32 Bit and works fast in MINESWEEPER ONLY. I tried it in Grand Chase and Farm Frenzy; the scan won't ends because its still slow and even the scan is done, there is no address being found (maybe because in just tested it for 4 bytes).
I like to use VirtualProtectEx and VirtualAllocEx to enable to scan those PAGE_GUARD and write on it. Therefore I am able to obtain the specific address that I want but I can't do it because it is still slow. I make the PAGE_GUARD'ed PAGE into EXECUTE_READWRITE it will make more bytes to scan. It will make the App slower.
If i have a file ( appres.exe ) in the resources of my VB 2008 Application (myVbApp.exe), how can I start from there? I don't want to save it (appres.exe) somewhere else before start, i want only myVbApp.exe, no more files.
Retrieve the EXE from the resources:
Dim l as System.IO.Stream = Reflection.Assembly.GetEntryAssembly.GetManifestResourceStream(String.Format("{0}.{1}", "ApplicationProjectName", "YourExeName"))
Then save it to temp folder - example method:
Private Sub SaveStreamToFile(ByVal p_stream As Stream, ByVal p_fileName As String)
Dim l_streamWriter As System.IO.FileStream = System.IO.File.Create(p_fileName)
Try
Dim l_bytes(65536) As Byte
Dim l_offset As Integer = 0
Dim l_readBytes As Integer
Do
l_readBytes = p_stream.Read(l_bytes, 0, 65536)
l_streamWriter.Write(l_bytes, 0, l_readBytes)
l_offset += l_readBytes
Loop While (l_readBytes > 0)
Debug.WriteLine("Num Of bytes Read: " + l_offset.ToString)
Catch ex As Exception
'log error
Finally
p_stream.Close()
l_streamWriter.Close()
End Try
End Sub
Now that you got the EXE in a temp folder, you can regulary lunch it using:
Process.Start("EXE_PATH")
And delete it once the process is done.
You can try this :
Dim SetupPath As String = Application.StartupPath & "\appres.exe"
Using sCreateMSIFile As New FileStream(SetupPath, FileMode.Create)
sCreateMSIFile.Write(My.Resources.yourexefilename, 0, My.Resources.Yourexefilename.Length)
End Using
Process.Start(SetupPath)