Read and edit the contents of a gzip file? - vb.net

I am trying to read and edit a file within a gzip file. I can do this with .zip files, but I get an error when trying to read the .gzip file.
Search results so far only talk about compressing or decompressing .gzip files.
If relative, the .gzip file (as per file properties) actually has a ".dat" extension. The file I need to edit within it doesn't have any extension.
Using archive As ZipArchive = Compression.ZipFile.Open(Path.Combine(SelectedWorld, "level.dat"), ZipArchiveMode.Update)
Dim entry As ZipArchiveEntry = archive.GetEntry("level")
Dim s As String = ""
Using sr As New StreamReader(entry.Open())
s = sr.ReadToEnd()
End Using
Dim M As Match = Regex.Match(s, "LevelName")
If M.Success Then
MsgBox(M.Value)
'edit word after "LevelName" <<I'm going to need help with this too.
End If
End Using
The above code throws the following error:
System.IO.InvalidDataException: 'End of Central Directory record could not be found.'
Trying the following doesn't seem to have the right stuff to read/modify a file.
Using archive As IO.Compression.GZipStream = IO.Compression.GZipStream
I have found little else for dealing with these types of files. Any help would be greatly appreciated.

A gzip file is not a zip file. Two entirely different things. The error about not finding an end-of-central-directory record is something only found in a zip file.
A zip file is an archive, with files stored within that are independently compressed. That permits removing and adding some files without having to recompress the other files. Though the whole thing will need to be copied to move things around.
A gzip file stores only one compressed file. If you want to edit that one file, then simply gunzip it, edit it, and then re-gzip it.
Often the one compressed file in a gzip file is itself an uncompressed tar archive of many files. The extension of the file will be .tar.gz. If you want to edit the tar archive, again you would gunzip it to get a .tar file, edit it with the tar command, which can delete and append files, and then re-gzip it.

I got it working using:
Imports Cyotek.Data.Nbt
NewName = InputBox("Enter New Name")
Dim MyFile As String = Path.Combine(SelectedWorld, "level.dat")
Dim document As NbtDocument = NbtDocument.LoadDocument(MyFile)
Dim root As TagCompound = document.DocumentRoot
root.Name = "Data"
Dim TC As TagCompound = root.GetCompound("Data")
Dim MyTag As Tag = TC.GetTag("LevelName")
MyTag.SetValue(NewName)
document.Save(MyFile)

Related

VB.NET open a Text File within the same folder as my Forms without writing Full Path

I found a similar question but it was 5 years 8 months old, had 2 replies and neither worked for me (VB.Net Read txt file from current directory)
My issue is that when I use the following code:
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\Username_And_Password_Raw.txt")
Dim usernameAndPassword = Split(fileReader, ",")
I get an error saying:
System.IO.FileNotFoundException: 'Could not find file 'C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows\Username_And_Password_Raw.txt'.'
I have tried using all the different Applications.BLANKPath options I can find (ie; StartupPath, CommonAppDataPath, etc.) and they all return essentially the same error only with a different location.
This is the folder layout of my TXT File - I know it's a terrible, incredibly insecure and generally awful way of storing login information but this is just for a NEA so will never ever actually be used
This is the actual path of the TXT File if it helps
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\Username_And_Password_Raw.txt
The startup path is where your exe is located. That and all supporting files get copied to a binary directory when you compile in visual studio, in your case
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows
But what you're trying to do, reference the file where it sits in your solution, is probably not the best way to do it, and your code above will work (with a change, will mention later) if you change the properties of the file in the solution.
Right click on the file in the Solution Explorer Username_And_Password_Raw.txt, select Properties. Modify Copy to Output Directory to either Copy always / Copy if newer, depending on your requirement. Now that file will copy to the same directory your exe is in, and the code above should work.
Note, when creating a path, don't use string concatenation because you may have too many or too few \; use Path.Combine:
Dim filePath = Path.Combine(Application.StartupPath, "Username_And_Password_Raw.txt"
Dim fileContents = My.Computer.FileSystem.ReadAllText(filePath)

Missing txt file from Visual Basic

I am working in Visual Basic 2017. I have tried to add the file to the Debug folder, but then it just shows that the txt file ienter image description heres missing. I don't have the option under the "Word Solution".. How can I make the file show up? It keeps telling me it doesn't exist.
Dim inFile As IO.StreamReader
Const FileName As String = "words.txt"
Dim subscript As Integer
You can get the path of the directory (Debug or Release or any other) of the *.exe file with:
Dim directory as String = My.Application.Info.DirectoryPath
Using this information, you can then construct the full path with
Dim path As String = IO.Path.Combine(directory, FileName)
If IO.File.Exists(path) Then
...
You can check in Windows File Explorer to see where the file actually is (notice the Copy Path on the ribbon). In File Explorer you will see that the .exe you are running is down 2 directories from the Words Project directory. The double dots in the path is an old DOS way to navigating around directories without having to type out the whole path. This tells the compiler to find the file up 2 directories from the current directory.
For testing purposes this will work. For a release version you could add the file to Resources and access it the same way in any version.
You don't need a stream for a text file. .ReadAllLines returns an array of the lines in the text file
Private Sub OpCode()
Dim words = File.ReadAllLines("..\..\words.txt")
End Sub

File not copy to correct directory

I am trying to copy a file from a network drive then move to the different folder. Somehow is not moving the file to the directory I specified. After executing the read file code, the file is copy in the same directory.(see pic)
I have try the same code from my local drive and it works fine.
'copy the file
File.Copy(Path.Combine("\\swnas.swmed.org\Phytel\", Dts.Variables("File").Value.ToString), Path.Combine("\\swnas.swmed.org\Phytel\Raw\MCKPP\Processed", insertNewName), True)
'read the file
objStreamReader = New StreamReader(Path.Combine("\\swnas.swmed.org\Phytel\Raw\MCKPP\Processed", insertNewName))
'overwrite the file
objWriter = New StreamWriter(Dts.Variables("File").Value.ToString, False)
I'd take a minute and make sure there are no odd permission rules being applied to the directory you are copying/moving to.

Read File name and put it into Variable

I am trying to find a way to read a specific file name in a directory and then put the file name into a variable. In my program I have a batch file that zips a folder called logs and then changes the name of zip to username_date_time.zip.
So basically if the filename was jobs_03152015_1315.zip I would want the entire file name but not the path stored into a variable. The file starts off on the user's local machine. It is then uploaded into a network share.
The network path will be uploaded to a database for others to view. I want to just add the unique file name to the end of a pre set path. Here is the code I am using.
Dim filePath As String = "c:\temp\logs\"
If (System.IO.Directory.Exists(filePath)) Then
For Each file As String In filePath
If file.Contains(".zip") Then
Dim zip As String = file
testbox.Text = zip
Exit For
End If
Next
End If
You can enumerate all files using the GetFiles() method of the static (shared in VB) Directory class, see msdn.
Assuming you have more then 1 file I add the files to a listbox control. But you could change that if you wish. I get the filename using the Path class. You will find a lot other helpful functions in this class.
Dim searchPath = "C:\temp\logs"
Dim files = Directory.GetFiles(path, "*.zip")
For Each file In files
listbox1.Items.Add(path.GetFileName(file))
Next
This should do it.
Your loop doesn't read anything. The string variable filePath is just the name of the directory, not a list of the files in that directory. Calling For Each over a string simply enumerates each character contained in the string
To get a list of files contained in that folder you need Directory.EnumerateFiles() and pass the filePath variable and the extension required.
It seems that you are interested only to find if that folder contains at least one file with zip extension. If this is the case then you could remove the explicit loop and write simply
Dim file = Directory.EnumerateFiles(filePath, "*.zip").FirstOrDefault()
If file IsNot Nothing Then
testbox.Text = Path.GetFileName(file)
End If
Using Path.GetFileName will return just the file without the path part
Try this code :
Dim FilePath As String = "c:\temp\logs\"
If (System.IO.Directory.Exists(FilePath)) Then
For Each File As String In System.IO.Directory.EnumerateFiles(FilePath)
If File.Contains(".zip") Then
Dim info As New System.IO.FileInfo(File)
zip = info.Name
testbox.Text = zip
Exit For
End If
Next
End If

How do I get a text file to be a part of my build?

I wrote a program that reads from text files and can create them to load and save data. I have a few files that are the "default" data that are loaded as soon as the program start. The files are loaded by a static reference. My code runs fine before I publish it, but obviously when I publish it, the static references no longer work. I don't know how to add the default data to the build as distinct text files so that I can still reference it after the build.
I imagine being able to build the program and have some sort of folder that accompanies the executable with the default data files in them that I can easily reference, but I don't know how to do that (or if there is a better way).
Below is the start of the code I use to read from the file. Currently, the default data's file name is passed statically into the sub and is used to identify the file to read from, so I'd like to have a published file that I can do the same thing with.
Try
Dim sr As New IO.StreamReader(FileName)
Dim strLine As String = ""
Do Until sr.EndOfStream
strLine = sr.ReadLine
'Code that interprets the data in the file
Note: I've tried adding the files as "Resources" but I can't seem to reference the file as a text file; I can only retrieve the massive wall of text contained within the document which won't work with the above code (unless of course I'm missing something).
If you could clarify:
How do I add a file to a build so that I can still access it
collectively by a file name?
How will my code reference the files (e.g. by
"My.Resources.filename"?) in the final build?
You can add the file to the build as either a content file or an embedded resource.
For a content file, set the Build Action of the file to 'content', and Copy to Output Directory to 'Copy Always' in the file properties. You can then access the file like this:
FileName = Application.StartupPath() = + FileName
Dim sr As New IO.StreamReader(FileName)
...
To embed the file as a resource you have to set the Build Action of the file to 'Embedded Resource' and Copy to Output Directory to false.
This Microsoft support page has a walkthough about accessing embedded resources. The code would be something like this:
Dim sr As StreamReader
Dim thisAssembly As Assembly
thisAssembly = Assembly.GetExecutingAssembly()
sr = New StreamReader(thisAssembly.GetManifestResourceStream("NameSpace." + FileName))
Dim strLine As String = ""
Do Until sr.EndOfStream
strLine = sr.ReadLine
'Code that interprets the data in the file
...
Replace NameSpace with the namespace of your application (Project Properties -> Application -> root namespace)
You also have to add Imports System.Reflection at the top of your code file.
Using an embedded resource has the advantage of less files to manage, and you don't have to keep track of paths.