I'm looking at removing a large section of bytes from within a file and then inserting a new large section of bytes starting in the same place the original removed bytes did, all using C#. Does anyone know how to go about this? I can't see to find any help online.
Any help would be much appreciated!
Thanks.
This should get you started.
Steps are as follow:
Find a position you want to edit.
Prepare your new data
Write
.
using System;
using System.Text;
using System.IO;
namespace Test
{
class Program
{
static void Main(string[] args)
{
using (BinaryWriter writer = new BinaryWriter(File.Open("TextFile1.txt", FileMode.Open, FileAccess.ReadWrite)))
{
int offset = 1; //position you want to start editing
byte[] new_data = new byte[] { 0x68, 0x69 }; //new data
writer.Seek(offset, SeekOrigin.Begin); //move your cursor to the position
writer.Write(new_data);//write it
}
}
}
}
Related
With std::filesystem::resize_file in C++, it is possible to change the size of a file without opening the file.
Is there any similar function in C#, which allows changing the size of a file without opening it?
I think opening a file as a FileStream and saving it again with a new size will be slower.
Using FileStream.SetLength() will be about as fast as you can make it.
It ends up calling the Windows API to set the length of the file, the same as the std::filesystem::resize_file().
So you just need to do something like this, and it will be fast enough:
using (var file = File.Open(myFilePath, FileMode.Open))
{
file.SetLength(myRequiredFileSize);
}
The implementation of FileStream.SetLength() is:
private void SetLengthCore(long value)
{
Contract.Assert(value >= 0, "value >= 0");
long origPos = _pos;
if (_exposedHandle)
VerifyOSHandlePosition();
if (_pos != value)
SeekCore(value, SeekOrigin.Begin);
if (!Win32Native.SetEndOfFile(_handle)) {
int hr = Marshal.GetLastWin32Error();
if (hr==__Error.ERROR_INVALID_PARAMETER)
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig"));
__Error.WinIOError(hr, String.Empty);
}
// Return file pointer to where it was before setting length
if (origPos != value) {
if (origPos < value)
SeekCore(origPos, SeekOrigin.Begin);
else
SeekCore(0, SeekOrigin.End);
}
}
(Note that SeekCore() just calls the the Windows API SetFilePointer() function.)
Doing this does NOT read the file into memory.
Also, the Windows API function SetEndOfFile() does not write to the extended region, so it is fast. The documentation states If the file is extended, the contents of the file between the old end of the file and the new end of the file are not defined. - this is as a result of data not being written to the extended region.
As test, I tried the following code:
using System;
using System.Diagnostics;
using System.IO;
namespace Demo
{
public class Program
{
public static void Main()
{
string filename = #"e:\tmp\test.bin";
File.WriteAllBytes(filename, new byte[0]); // Create empty file.
var sw = Stopwatch.StartNew();
using (var file = File.Open(filename, FileMode.Open))
{
file.SetLength(1024*1024*1024);
}
Console.WriteLine(sw.Elapsed);
}
}
}
My E:\ drive is a hard drive, not an SSD.
The output was: 00:00:00.0003574
So it took less than a hundreth of a second to extend the file to 1GB in size.
I'm trying to hash a file using SHA1. The result looks like this: B7-DB-B9-93-E7-2F-6F-EB-6D-CD-CC-A8-DE-D2-F1-01-6E-8A-53-BC
How to I replace dashes to empty string or just remove them?
The code trying to replace the dashes, but it seems like it don't change anything and dashes are still in place.
using (HashAlgorithm hashSHA1 = new SHA1Managed())
using (Stream file = new FileStream(ofdBrowse.FileName, FileMode.Open, FileAccess.Read))
{
byte[] hash = hashSHA1.ComputeHash(file);
txtSHA1.Text = BitConverter.ToString(hash).Replace("-", "");
}
Difference between dash and hyphen?
http://msdn.microsoft.com/en-us/library/3a733s97.aspx
Not really sure. Just my guess in the dark.
The code you've give definitely removes the dashes. Short but complete program to demonstrate that:
using System;
using System.IO;
using System.Security.Cryptography;
class Test
{
static void Main(string[] args)
{
using (HashAlgorithm hashSHA1 = new SHA1Managed())
{
// Actual data doesn't matter
using (Stream data = new MemoryStream())
{
byte[] hash = hashSHA1.ComputeHash(data);
Console.WriteLine(BitConverter.ToString(hash).Replace("-", ""));
}
}
}
}
So, potential cause of your problem:
You're not running the build you think you are
You've got other code which does the hashing but doesn't have the Replace call
You're looking at the wrong bit of the UI :)
It's hard to really guess which of those (or anything else) is the problem, but that code isn't it...
I have a binary file to which I want to append a chunk of data at the end of the file, how can I achieve this using C# and .net? Also is there anything to consider when writing to the end of a binary file? Thanks a lot for your help.
private static void AppendData(string filename, int intData, string stringData, byte[] lotsOfData)
{
using (var fileStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.None))
using (var bw = new BinaryWriter(fileStream))
{
bw.Write(intData);
bw.Write(stringData);
bw.Write(lotsOfData);
}
}
You should be able to do this via the Stream:
using (FileStream data = new FileStream(path, FileMode.Append))
{
data.Write(...);
}
As for considerations - the main one would be: does the underlying data format support append? Many don't, unless it is your own raw data, or text etc. A well-formed xml document doesn't support append (without considering the final end-element), for example. Nor will something like a Word document. Some do, however. So; is your data OK with this...
Using StreamWriter and referencing DotNetPerls, make sure to add the True boolean to the StreamWriter constructor, if otherwise left blank, it'll overwrite as usual:
using System.IO;
class Program
{
static void Main()
{
// 1: Write single line to new file
using (StreamWriter writer = new StreamWriter("C:\\log.txt", true))
{
writer.WriteLine("Important data line 1");
}
// 2: Append line to the file
using (StreamWriter writer = new StreamWriter("C:\\log.txt", true))
{
writer.WriteLine("Line 2");
}
}
}
Output
(File "log.txt" contains these lines.)
Important data line 1
Line 2
This is the solution that I was actually looking for when I got here from Google, although it wasn't a binary file though, hope it helps someone else.
I have a few reports that are exported to Excel. The problem is whereever there are special characters, it is being replaced by some funny symbols
For example, '-'(hyphen) was replaced by –...
Any help to solve the problem??
The most straight forward way is to encode the text file as UTF-8. I ran the following code, opened the resulting hyphen.txt file in Excel 2007 and it worked as expected:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var hyphen = "\u2010\r\n";
var encoding = Encoding.UTF8;
var bytes = encoding.GetBytes(hyphen);
using (var stream = new System.IO.FileStream(#"c:\tmp\hyphen.txt", System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
{
stream.Write(bytes, 0, bytes.Length);
}
}
}
}
This is the code -- view at PasteBin.
I am trying to read PCM samples from a (converted) MP3 file using NAudio, but failing as the Read method returns zero (indicating EOF) every time.
Example: this piece of code, which attempts to read a single 16-bit sample, always prints "0":
using System;
using NAudio.Wave;
namespace NAudioMp3Test
{
class Program
{
static void Main(string[] args)
{
using (Mp3FileReader fr = new Mp3FileReader("MySong.mp3"))
{
byte[] buffer = new byte[2];
using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(fr))
{
using (WaveStream aligned = new BlockAlignReductionStream(pcm))
{
Console.WriteLine(aligned.WaveFormat);
Console.WriteLine(aligned.Read(buffer, 0, 2));
}
}
}
}
}
}
output:
16 bit PCM: 44kHz 2 channels
0
But this version which reads from a WAV file works fine (I used iTunes to convert the MP3 to a WAV so they should contain similar samples):
static void Main(string[] args)
{
using (WaveFileReader pcm = new WaveFileReader("MySong.wav"))
{
byte[] buffer = new byte[2];
using (WaveStream aligned = new BlockAlignReductionStream(pcm))
{
Console.WriteLine(aligned.WaveFormat);
Console.WriteLine(aligned.Read(buffer, 0, 2));
}
}
}
output:
16 bit PCM: 44kHz 2 channels
2
What is going on here? Both streams have the same wave formats so I would expect to be able to use the same API to read samples. Setting the Position property doesn't help either.
You probably need to read in larger chunks. NAudio uses ACM to perform the conversion from MP3 to WAV, and if your target buffer isn't big enough, the codec may refuse to convert any data at all. In other words, you need to convert a block of samples before you can read the first sample.
WAV files are a different matter as it is nice and easy to read a single sample from them.