I am working in VB 2010 on a one-time pad software.
The problem is the following. I have a txt file with many continous characters like this "KHKJHDKJDHAKHDAKHDAKHAKDHADHAKJDHASJDHA", i need to read a variable number of this characters and after replace it with a same number of dots (Ex. read four chars "KHKJ" replaced them with four dots "....HDKJDETCETC"). After this i will have to memorize the position of the last dot, in the txt key file, for a next read of the remaining keys. How to do it?
Thanks to info.de for the quick reply and my apologize for not having deepened my request. Let me explain better, my project is a Vernam chat and i need to have one single keys txt file that must remain synchronized in some way between broadcaster and receiver. When I send the message the key used must be deleted and who receives after decripting delete it too.
The goal is synchronizing the two key files!
I thought something like this:
'READ PART
Using stream = File.OpenRead("c:\key.txt")
stream.Seek(v, SeekOrigin.Begin)
Dim b = New Byte(a - 1) {} '
stream.Read(b, 0, a)
Dim str = Encoding.ASCII.GetString(b)
txtPad.Text = str ' portions of code read in txt for encodinh/decoding
End Using
v = startup position for read in file key.txt
a= lenght of text in key.txt to be taken = lenght of text to encode
WRITE PART
Using stream = File.OpenWrite("c:\key.txt")
stream.Seek(v, SeekOrigin.Begin)
Dim b = New Byte(a - 1) {}
stream.Write(b, 0, 1)
End Using
But how can I overwrite (no delete) with dots taken characters using this code?
And above all what will be the next coordinates to repeat a subsequent encoding/decoding operation? (V changes constantly)
Thank's in advance.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'//--- -----------------------------------------------
'//--- KHKJHDKJDHAKHDAKHDAKHAKDHADHAKJDHASJDHA-line1#
'//--- KHKJHDKJDHAKHDAKHDAKHAKDHADHAKJDHASJDHA-line2#
Dim lines() As String = System.IO.File.ReadAllLines(Application.StartupPath & "\TextFile1.txt")
Dim iReplaceLength As Integer
Dim sReplaceSubString As String
For Each line As String In lines
MessageBox.Show(line)
sReplaceSubString = "KHKJ"
iReplaceLength = sReplaceSubString.Length
MessageBox.Show(line.Replace(sReplaceSubString.ToCharArray, New String("."c, iReplaceLength)))
MessageBox.Show(line.Substring(iReplaceLength, line.Length - iReplaceLength))
Next
End Sub
End Class
Related
I have a question which asks me to calculate something from an input file. The problem is, the lines in the file don't use any special character as delimiter, like , or |. I will show it down below.
Data Communication
20
Visual Basic
40
The output I need to write to another file should look like this:
Data communication 20
Visual Basic 40
Total Books : 60
The problem is, how can I specify the delimiter? Like when there is a symbol as in strArray = strLine.Split(","). Since there is nothing I can use as delimiter, how can I split the file content?
There's no real need to split the text in the input file, when you can read a file line by line using standard methods.
You can use, e.g., a StreamReader to read the lines from the source file, check whether the current line is just text or it can be converted to a number, using Integer.TryParse and excluding empty lines.
Here, when the line read is not numeric, it's added as a Key in a Dictionary(Of String, Integer), unless it already exists (to handle duplicate categories in the source file).
If the line represents a number, it's added to the Value corresponding to the category Key previously read, stored in a variable named previousLine.
This setup can handle initial empty lines, empty lines in the text body and duplicate categories, e.g.,
Data Communication
20
Visual Basic
40
C#
100
Visual Basic
10
Other stuff
2
C++
10000
Other stuff
1
If a number is instead found in the first line, it's treated as a category.
Add any other check to handle a different structure of the input file.
Imports System.IO
Imports System.Linq
Dim basePath = "[Path where the input file is stored]"
Dim booksDict = New Dictionary(Of String, Integer)
Dim currentValue As Integer = 0
Dim previousLine As String = String.Empty
Using sr As New StreamReader(Path.Combine(basePath, "Books.txt"))
While sr.Peek > -1
Dim line = sr.ReadLine().Trim()
If Not String.IsNullOrEmpty(line) Then
If Integer.TryParse(line, currentValue) AndAlso (Not String.IsNullOrEmpty(previousLine)) Then
booksDict(previousLine) += currentValue
Else
If Not booksDict.ContainsKey(line) Then
booksDict.Add(line, 0)
End If
End If
End If
previousLine = line
End While
End Using
Now, you have a Dictionary where the Keys represent categories and the related Value is the sum of all books in that category.
You can Select() each KeyValuePair of the Dictionary and transform it into a string that represents the Key and its Value (Category:Number).
Here, also OrderBy() is used, to order the categories alphabetically, in ascending order; it may be useful.
File.WriteAllLines is then called to store the strings generated.
In the end, a new string is appended to the file, using File.AppendAllText, to write the sum of all books in all categories. The Sum() method sums all the Values in the Dictionary.
Dim newFilePath = Path.Combine(basePath, "BooksNew.txt")
File.WriteAllLines(newFilePath, booksDict.
Select(Function(kvp) $"{kvp.Key}:{kvp.Value}").OrderBy(Function(s) s))
File.AppendAllText(newFilePath, vbCrLf & "Total Books: " & booksDict.Sum(Function(kvp) kvp.Value).ToString())
The output is:
C#:100
C++:10000
Data Communication:20
Other stuff:3
Visual Basic:50
Total Books: 10173
Sure.. System.IO.File.ReadAllLines() will read the whole file and split into an array based on newlines, so you'll get an array of 4 elements. You can process it with a flipflop boolean to get alternate lines, or you can try and parse the line to a number and if it works, then its a number and if not, it's a string. If it's a number take the string you remembered (using a variable) from the previous loop
Dim arr = File.ReadALlLines(...)
Dim isStr = True
Dim prevString = ""
For Each s as String in arr
If isStr Then
prevString = s
Else
Console.WriteLine($"The string is {prevString} and the number is {s}")
End If
'flip the boolean
isStr = Not isStr
Next s
I used File.ReadAllLines to get an array containing each line in the file. Since the size of the file could be larger than the sample shown, I am using a StringBuilder. This save having to throw away and create a new string on each iteration of the loop.
I am using interpolated strings indicated by the $ preceding the quotes. This allows you to insert variables into the string surrounded by braces.
Note the Step 2 in the For loop. i will increment by 2 instead of the default 1.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lines = File.ReadAllLines("input.txt")
Dim sb As New StringBuilder
Dim total As Integer
For i = 0 To lines.Length - 2 Step 2
sb.AppendLine($"{lines(i)} {lines(i + 1)}")
total += CInt(lines(i + 1))
Next
sb.AppendLine($"Total Books: {total}")
TextBox1.Text = sb.ToString
End Sub
Our app requires us to write out a large list of key, GUID value pairs for export to a plain text file.
6004, aa20dc0b-1e10-4efa-b683-fc98820b0fba
There will be potentially millions of these GUIDs, and there may not be a lot of room on the device where the file will be written, so is there a more efficient way to print the GUID to keep the file size down?
I experimented with Hex encoding
Dim g As Guid = Guid.NewGuid
Dim sb As New Text.StringBuilder
For Each b As Byte In g.ToByteArray
sb.Append(String.Format("{0:X2}", b))
Next
Console.WriteLine(sb.ToString)
this got it down to 32 chars, each line is a bit shorter:
9870, EBB7EF914C29A6459A34EDCB61EB8C8F
Are there any other approaches to write the GUIDs to the file that are more efficient?
I agree with previous comment, SQL would be ideal (or another DB) text files can be very unstable. Just done some quick testing iterating over millions of GUIDs and storing in text files.
Here is the outcome, basically anything more than 1 million guids would start to cause issues. You can store safely 10 million, but the file would struggle to open (on an average PC) as its > 150mb see below:
The code I used is below for you if wanted to try out. I know its not perfect, but gives you an idea of where the time goes. Main conclusions are to append the files with a bulk append, don't try to append each GUID individually if you can help it. This saves a large amount of processing and time!
Even if you convert to other formats like base or binary, I think you will still get similar variations on the file size, don't forget, you are still just saving as a text file, binary will no doubt be a larger file size due to string length!
Hope this helps comment back if you need anything!
Chicken
Dim Report_List As List(Of String)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Report_List = New List(Of String)
Dim Zeros As Integer = 2
Do While Zeros < 8
Dim sw As Stopwatch = New Stopwatch
sw.Start()
Dim CountName As String = "1" & Microsoft.VisualBasic.Left("00000000000000000000000", Zeros)
Dim CountNum As Integer = CInt(CountName)
Dim Master_String As System.Text.StringBuilder = New System.Text.StringBuilder
For i = 1 To CountNum
Dim g As Guid = Guid.NewGuid
'Dim sb As New System.Text.StringBuilder
'For Each b As Byte In g.ToByteArray
' sb.Append(String.Format("{0:X2}", b))
'Next
'Master_String.AppendLine(sb.ToString)
'Master_String.AppendLine(sb.ToString)
Master_String.AppendLine(Convert.ToBase64String(g.ToByteArray))
i += 1
Next
Using sr As StreamWriter = New StreamWriter("c:\temp\test-" & CountName & ".txt", False)
sr.Write(Master_String.ToString)
End Using
sw.Stop()
Report_List.Add(sw.Elapsed.ToString & " - " & CountName)
Zeros += 1
Loop
For Each lr In Report_List
Me.ListBox1.Items.Add(lr)
Next
End Sub
I dont know why my CSV writer skips some lines. I tried to export today a gridview and saw it by coincindence. The grid has 250 rows. It writes 1-60 and then goes on at 140-250. 61-139 are missing in the excel table?
to the code: First I create a list whith all columns, because the writer method shall be able to also write only specific columns, but this is another button.
Then the grid and the list is given to the csv Writer.
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim list As List(Of Integer) = New List(Of Integer)
For Each column As DataGridViewColumn In datagridview2.Columns
list.Add(column.Index)
Next
Module3.csvwriter(list, datagridview2)
MsgBox("exportieren beendet")
End Sub
The csv-Writer creates a csv-body-String for every datarow.
For each row, append every columnvalue to body if the columnindex is in the list.
The best is, that I have seen how the method build row 61, but then it is missing in the csv :/
Public Sub csvwriter(list As List(Of Integer), grid As DataGridView)
Dim body As String = ""
Dim myWriter As New StreamWriter(Importverzeichnis.savecsv, True, System.Text.Encoding.Default)
Dim i As Integer
For i = 0 To grid.Rows.Count - 1
For ix = 0 To grid.Columns.Count - 1
If list.Contains(ix) Then
If grid.Rows(i).Cells(ix).Value IsNot Nothing Then
body = body + grid.Rows(i).Cells(ix).Value.ToString + ";"
Else
body = body + ";"
End If
End If
Next
myWriter.WriteLine(body)
body = ""
Next
myWriter.Close()
End Sub
Has anyone an idea? Do I overlook something?
I found an answer.
1. The csv file is complete. every row is in there.
The problem was or is, that in my datarows is a sign " which escapes the delimiter ; sign.
To solve the problem I save the file now as .txt file,
because then the user gets asked everytime when he opens the file, which one is the delimiter, which is the escaping sign.. this way the user is forced to put in the right settings, while a .csv file uses standard configurations..
start=AKS-RHzlSXSftLGYdBNk.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1&
For every instance of the word 'start' I need to be able to get the text after the first full stop, right up until the & symbol. E.g. 'eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1'.
There will be more than one instance of this. They will need to be appended to a listbox.
What is the simplest/quickest way to do this? (Using possibly streamreader - text file)
The simplest and quickest way will be to read each line, and check if it .StartsWith("start="). If so, then get the .IndexOf(".") and the .IndexOf("&", <whereever the first indexOf was>). Get the .SubString which encompasses those two values. I'm sure you can write the code yourself from that ;)
I tested this function with a button click, output text each line on a textbox. I am sure you can adapt this to your code.
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
txtResults.Text = ""
Dim ParseString As String
ParseString = "start=123341.23124&kjdshfkjsdaksdstart=1231.2321312&kadhskjashdkjastart=1231.23126789898&skjdfhkjsd"
Dim Delimiters() As String = New String() {"start="}
Dim Words() As String
Words = ParseString.Split(Delimiters, CompareMethod.Text)
For Each Part In Words
Dim Middle As String
Middle = Part.Split(".").Skip(1).Take(1).FirstOrDefault()
Dim Good As String
Good = Middle.Split("&").FirstOrDefault()
txtResults.Text += Good + vbNewLine
Next
End Sub
Output was
23124
2321312
23126789898
Added 31104 lines to a string and ran, took about 11 seconds to run on my laptop. Might be too slow for your app?
I am trying to loop through the contents of a text file reading the text file line by line. During the looping process there is several times I need to use the files contents.
Dim xRead As System.IO.StreamReader
xRead = File.OpenText(TextBox3.Text)
Do Until xRead.EndOfStream
Dim linetext As String = xRead.ReadLine
Dim aryTextFile() As String = linetext.Split(" ")
Dim firstname As String = Val(aryTextFile(0))
TextBox1.Text = firstname.ToString
Dim lastname As String = Val(aryTextFile(0))
TextBox2.Text = lastname.ToString
Loop
Edit: What I am trying to do is read say the first five items in a text file perform some random processing then read the next 5 lines of the text file.
I would like to be able to use the lines pulled from the text file as separated string variables.
It is not clear why you would need to have 5 lines stored at any time, according to your code sample, since you are only processing one line at a time. If you think that doing 5 lines at once will be faster - this is unlikely, because .NET maintains caching internally, so both approaches will probably perform the same. However, reading one line at a time is a much more simple pattern to use, so better look into that first.
Still, here is an approximate version of the code that does processing every 5 lines:
Sub Main()
Dim bufferMaxSize As Integer = 5
Using xRead As New System.IO.StreamReader(TextBox3.Text)
Dim buffer As New List(Of String)
Do Until xRead.EndOfStream
If buffer.Count < bufferMaxSize Then
buffer.Add(xRead.ReadLine)
Continue Do
Else
PerformProcessing(buffer)
buffer.Clear()
End If
Loop
If buffer.Count > 0 Then
'if line count is not divisible by bufferMaxSize, 5 in this case
'there will be a remainder of 1-4 records,
'which also needs to be processed
PerformProcessing(buffer)
End If
End Using
End Sub
Here is mine . Rely easy . Just copy the location from the file and copy1 folder to does locations . This is my first program :) . ready proud of it
Imports System.IO
Module Module1
Sub Main()
For Each Line In File.ReadLines("C:\location.txt".ToArray)
My.Computer.FileSystem.CopyDirectory("C:\Copy1", Line, True)
Next
Console.WriteLine("Done")
Console.ReadLine()
End Sub
End Module