Sometimes don't you want to use ram as you go, instead of loading giant files into ram? Here is an example of how to utilize Virtual Memory in Visual Basic.
Code:
The following Visual Basic code uses the MemoryMappedFile.CreateFromFile(FileName) method, although MemoryMappedFile has other methods available, they are not available in this article. This example generates fake DNA sequences to demonstrate how to use Virtual Memory. This example is designed to work if you simply create a new Visual Basic.Net project, and replace all of Form1's code with the following code and click run:
Option
Strict
On
Imports
System
System.Text
System.IO.MemoryMappedFiles
Public
Class
Form1
'This will hold the references for the files stored in Virtual Memory
Private
Lines
As
New
List(Of MemoryMappedFile)
'This is used to generate random characters for the file
Random
Random(1)
'This is used for flashing the seeking... 's flashing .'s
LastSeekingString
String
= Space(3)
'this is the path to the folder where Virtual Ram files will be stored
Path
= My.Computer.FileSystem.SpecialDirectories.Desktop &
"\DatFiles\"
'A richtextbox will be used for displaying data
Friend
WithEvents
RichTextBox1
DBRichTextBox
With
{.Parent =
Me
, .Width = 565, .BackColor = Color.FromArgb(33, 33, 33), .ForeColor = Color.White}
'These scrollbars scroll the data offsets/line numbers
VScrollBar1
VScrollBar
}
HScrollBar1
HScrollBar
'This aligns the blocks of data, regardless of the line numbers using the .PadRight feature later
Dim
LineLabelPadWidth
Integer
= 10
'Calculate how many lines are visible in the richtextbox
ReadOnly
Property
MaxVisibleLines
Get
'Get the height of the current font
TextHieght
= RichTextBox1.Font.Height
'calculate how many lines the richtextbox can hold
Return
(RichTextBox1.ClientRectangle.Height \ TextHieght) - 2
End
VisibleCharactersInLine
CharacterWidth
'Calculate the width of a character(for monospaced font consolas, the width is half of the height)
CharacterWidth = RichTextBox1.Font.Height \ 2
'Calculate how many data characters are in a line
Characters
= (RichTextBox1.ClientRectangle.Width \ CharacterWidth) - LineLabelPadWidth - 1
'return the result
#Region "Events"
Sub
Form1_FormClosing(sender
Object
, e
FormClosingEventArgs)
Handles
.FormClosing
'Dispose each memorymappedfile before exiting the program
For
Each
mmf
MemoryMappedFile
In
mmf.Dispose()
Next
If
My.Computer.FileSystem.DirectoryExists(Path)
Then
'Delete the files if they exist
My.Computer.FileSystem.DeleteDirectory(Path, FileIO.DeleteDirectoryOption.DeleteAllContents)
Form1_Load(sender
EventArgs)
MyBase
.Load
.Text =
"System.IO.MemoryMappedFiles.MemoryMappedFile Example"
Try
'Add the scroll event handler for the scrollbars
AddHandler
VScrollBar1.Scroll,
AddressOf
ScrollBar_Scroll
HScrollBar1.Scroll,
'Create the directory to store the virtual memory files in
My.Computer.FileSystem.CreateDirectory(Path)
'Disable the richtextboxes scrollbars(because we are using our own)
RichTextBox1.ScrollBars = RichTextBoxScrollBars.None
'make richtextbox1 readonly
RichTextBox1.
=
True
'Make the form double buffered
.DoubleBuffered =
'Position all controls
DoLayout()
'randomize the timer
Randomize()
'Create a stringbuilder reference
SB
StringBuilder
Line
= 0
To
99
' Generate 100 200000 Character dummy DNA data lines.
'Assign a new instance of stringbuilder to the reference
SB =
'Generate Each Line's Data(Each line will, have its own file for VRAM
LineCharacters
199999
' Make each line 200000 chars long
'Append a random character to the stringbuilder
SB.Append(GetRandomGeneChar)
'Generate a filename for the current line
FileName
= Path &
"DataFile"
& Line.ToString &
".Dat"
'Use a file stream to write to the file
Using FS
IO.FileStream(FileName, IO.FileMode.CreateNew)
'convert the string into an array of byte
Array
Byte
() = Encoding.ASCII.GetBytes(SB.ToString)
'write the array to the stream
FS.Write(Array, 0, Array.Count)
'close the file stream
FS.Close()
'Clear the array
Array = {}
GC.Collect()
Using
'create a new memorymapped file, this locks the file for exclusive use with your program
MemoryMappedFile = MemoryMappedFile.CreateFromFile(FileName)
'Add a reference to the loaded memorymapped file to the list of memorymappedfiles(one entire file per line)
Lines.Add(MemoryMappedFile)
'Set Richtextbox1 to have a monospaced font
RichTextBox1.Font =
Font(
"consolas"
, 16)
'Since each line will be 200k Characters long, we need to set the horizontal scrollbar's maxvalue
HScrollBar1.Maximum = 200000 - VisibleCharactersInLine + 8
'reset the scrollpoint of hscrollbar
HScrollBar1.Minimum = 0
'calculate Vscrollbar's max value
VScrollBar1.Maximum = Lines.Count - MaxVisibleLines + 8
'reset the scrollpoint
VScrollBar1.Minimum = 0
' Highlight the concatenated output of the locationstring function and the displaytext function(highlight the chromosones characters)
HighlightChromies(locationString() & DisplayText())
Catch
ex
Exception
MsgBox(ex.StackTrace)
Form1_SizeChanged(sender
.SizeChanged
'reposition the controls on the form
'reset the maximum values of the scrollbars because the size of the richtextbox changed
'Each file is exactly 200000 characters long, and the scrollbar will not quite scroll to its max value(bug?), so we adjust with 8 characters
'1.) Calculate the location string
'2.) Calculate the display text
'3.) Concatonate the result of the two
'4.) Highlight the concatonated result of the two
:
ScrollBar_Scroll(sender
ScrollEventArgs)
'Choose the type of scroll event that was raised
Select
Case
e.Type
ScrollEventType.EndScroll
'If the user finished scrolling:
ScrollEventType.ThumbTrack
'The user is probably scrolling too fast
'to maintain good performance, so instead we just
'display information about
'the current selection
RichTextBox1.Text = SeekingString() & locationString()
Else
'The user is probably holding the buttons
'down on the scrollbar, so we don't want to
'use the processor intensive highlight sub until they have finished scrolling
RichTextBox1.Text = SeekingString() & locationString() & DisplayText()
#End Region
#Region "Functions"
Function
DisplayText()
'Create a new stringbuilder
'Scroll through the visible range of lines(using the scrollbar to determine the user selection
I
= VScrollBar1.Value
VScrollBar1.Value + MaxVisibleLines
'Call the GetData function to create a line of data
'Append that line of data to the stringbuilder
SB.Append(GetData(I, HScrollBar1.Value, VisibleCharactersInLine))
'retirm the final result, removing the last carriage return that was appended
SB.ToString.Substring(0, SB.Length - 1)
GetData(LineNumber
, Offset
, Length
)
'Create a reference to the current line's memorymappedfile
CurrentMemoryMappedFile
MemoryMappedFile = Lines(LineNumber)
'create an array to hold that line's bytes
Bytes(199999)
'Create a MemoryMappedViewAccessor to load data from that file
Using V
MemoryMappedViewAccessor = CurrentMemoryMappedFile.CreateViewAccessor
'Read the data into the Bytes Array
V.ReadArray(Of
)(0, Bytes, 0, 200000)
'Converting the bytes into a string, build a data line for display
(
"Line"
& LineNumber.ToString &
":"
).PadRight(LineLabelPadWidth,
" "
c) & Encoding.ASCII.GetString(Bytes.ToList.GetRange(Offset, Length).ToArray) & vbCrLf
'return a line that has the error message.
c) & ex.Message & vbCrLf
SeekingString()
'This is purly asthetic
'Add the appearence of animated dot dot dotting... working...
Space(3)
LastSeekingString =
"."
& Space(2)
".."
& Space(1)
"..."
LastSeekingString = Space(3)
"Seeking"
& LastSeekingString
GetRandomGeneChar()
Char
'Function Borrowed from Reed Kimble:)
'Randomly select one of "ACTG"
chars
"ATCG"
chars(Random.
(0, 4))
locationString()
'Generate the first line displayed in the richtextbox,
'that identifies exactly what information is being displayed.
"Map coordinates[X="
& HScrollBar1.Value.ToString &
", Y="
& VScrollBar1.Value.ToString &
"]"
& vbCrLf
#Region "Subs"
'Calculate the controls locations and sizes
RichTextBox1.Location =
Point(0, 0)
VScrollBar1.Left =
.ClientRectangle.Width - VScrollBar1.Width
VScrollBar1.Height =
.ClientRectangle.Height - HScrollBar1.Height
HScrollBar1.Left = 0
HScrollBar1.Width =
HScrollBar1.Top =
RichTextBox1.Width =
RichTextBox1.Height =
HighlightChromies(Text
'Generating RTF is faster than setting the selection color properties :)
'Create RTF Header
Header
"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 "
& RichTextBox1.Font.FontFamily.Name &
";}}"
& vbCrLf & _
"{\colortbl ;\red0\green128\blue0;\red0\green0\blue255;\red255\green165\blue0;\red255\green0\blue0;}"
"\viewkind4\uc1\pard\lang1033\f0\fs"
&
CInt
((RichTextBox1.Font.Size * 2)).ToString &
'Build RTF Code to highlight all occurrences of each of the following
Text = Text.Replace(
"G"
,
"\highlight3 G\highlight0"
'g
"A"
"\highlight1 A\highlight0"
'a
"C"
"\highlight4 C\highlight0"
'c
"T"
"\highlight2 T\highlight0"
't
'replace all carriage returns with the RTF code that indicates a carriage return
Text = Text.Replace(vbCrLf,
"\par"
& vbCr)
'Assemble all the parts of the RTF code, set the RTF property of the richtextbox
RichTextBox1.Rtf = Header & Text &
" \par "
& vbCrLf &
"}"
Inherits
RichTextBox
()
'The whole purpose of this
'inherited richtextbox
'is for the doublebuffering. thats it.