i have an XML file which holds alot of data.
For the moment i can read out every data in c# except a mp3 file which is hold as an base64 string in a child.elemt named Data with commentary line: "4 bytes float array converted to base64".
I am very new to c# and before just a beginner in php/java, so be indulgent.
I have attached the base64 string in a text file and the original mp3, maybe it helps.
Can you tell me how i can convert this back ? I already tryd to get single bytes out of the array to a stream and write it back as mp3 file, but atleast its 4 times bigger and absolute not near the same file and just holds in crap.
https://www.file-upload.net/download-12719496/base64string.rar.html
edit:
After the Help of L.B, i got this, thank you.
var mp3base64string = Convert.FromBase64String(child.Element("Data").Value);
using(FileStream file = File.Create(mp3datafilename)) {
using(BinaryWriter writer = new BinaryWriter(file)) {
for (int i = 0; i < mp3base64string.Length; i += 4) {
writer.Write((byte)(967.644334 f * BitConverter.ToSingle(mp3base64string, i)));
}
}
}
This code works and the output is exactly the same as original mp3, but don't ask how I got that magic number :) (Does author of xml think it is some kind of encryption/obfuscation?)
var buf = Convert.FromBase64String(File.ReadAllText(#"base64string.txt"));
int count = 0;
var buf2 = buf.GroupBy(x => count++ / 4)
.Select(g => (byte)(967.644334f * BitConverter.ToSingle(g.ToArray(), 0)))
.ToArray();
File.WriteAllBytes(#"base64string.mp3", buf2);
PS: A non-linq version will be faster....
Related
I plan on reading the marks from a text file and then calculating what the average mark is based upon data written in previous code. I haven't been able to read the marks though or calculate how many marks there are as BinaryReader doesn't let you use .Length.
I have tried using an array to hold each mark but it doesn't like each mark being an integer
public static int CalculateAverage()
{
int count = 0;
int total = 0;
float average;
BinaryReader markFile;
markFile = new BinaryReader(new FileStream("studentMarks.txt", FileMode.Open));
//A loop to read each line of the file and add it to the total
{
//total = total + eachMark;
//count++;
}
//average = total / count;
//markFile.Close();
//Console.WriteLine("Average mark:", average);
return 0;
}
This is my studentMark.txt file in VS
First of all, don't use BinerayRead you can use StreamReader for example.
Also with using statement is not necessary implement the close().
There is an answer using a while loop, so using Linq you can do in one line:
var avg = File.ReadAllLines("file.txt").ToArray().Average(a => Int32.Parse(a));
Console.WriteLine("avg = "+avg); //5
Also using File.ReadAllLines() according too docs the file is loaded into memory and then close, so there is no leak memory problem or whatever.
Opens a text file, reads all lines of the file into a string array, and then closes the file.
Edit to add the way to read using BinaryReader.
First thing to know is you are reading a txt file. Unless you have created the file using BinaryWriter, the binary reader will not work. And, if you are creating a binary file, there is not a good practice name as .txt.
So, assuming your file is binary, you need to loop and read every integer, so this code shoul work.
var fileName = "file.txt";
if (File.Exists(fileName))
{
using (BinaryReader reader = new BinaryReader(File.Open(fileName, FileMode.Open)))
{
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
total +=reader.ReadInt32();
count++;
}
}
average = total/count;
Console.WriteLine("Average = "+average); // 5
}
I've used using to ensure file is close at the end.
If your file only contains numbers, you only have to use ReadInt32() and it will work.
Also, if your file is not binary, obviously, binary writer will not work. By the way, my binary file.txt created using BinaryWriter looks like this:
So I'm assuming you dont have a binary file...
I am trying to read a binary file (.bin) and convert the resources of the file into a matrix. The code I use to get the file is here.
using (BinaryReader Reader = new BinaryReader(File.Open(string.Format("{0}{1}.bin", DefaultFilePath, "MyBinaryFile"), FileMode.Open)))
{
//the code to convert binary to AxB matrix here.
byteArray = Reader.ReadBytes(100000);
float myFloat = System.BitConverter.ToSingle(byteArray, 0);
}
I need to write a piece of code which can convert the resources of a binary file into a AxB matrix. From the code above, you can see that I convert binary file into Byte[], then to float, but I am stuck in here.
In Matlab, you can read .bin file easily and get the AxB array such as in this link.
How can I proceed?
If the file is just a long list of 32-bit floats, you already got the first value converter correctly. Now you just need to do the rest by adding a loop and incrementing the second argument for ToSingle by 4 each time.
Or, since you're already using a BinaryReader you could just use its ReadSingle method in a loop. If you want a two-dimensional matrix, using a multidimensional array might be a good idea.
// In reality you might want to figure out the array size based on the file size
float[,] floatArray = new float[5000, 32];
using (BinaryReader reader = new BinaryReader(File.Open(string.Format("{0}{1}.bin", DefaultFilePath, "MyBinaryFile"), FileMode.Open)))
{
for (x = 0; x < floatArray.GetLength(0); x++)
{
for (y = 0; y < floatArray.GetLength(1); y++)
floatArray[x, y] = reader.ReadSingle();
}
}
Note: you might need to flip things around depending on whether your data file and desired memory representation is row-major or column-major.
Also remember that multidimensional arrays are contiguous in memory, so if your file is huge, you might run into problems processing it.
Assuming my WAV file contains 16 bit PCM, How can I read wav file as double array:
using (WaveFileReader reader = new WaveFileReader("myfile.wav"))
{
Assert.AreEqual(16, reader.WaveFormat.BitsPerSample, "Only works with 16 bit audio");
byte[] bytesBuffer = new byte[reader.Length];
int read = reader.Read(bytesBuffer, 0, buffer.Length);
// HOW TO GET AS double ARRAY
}
Just use the ToSampleProvider extension method on your WaveFileReader, and the Read method will take a float[] with the samples converted to floating point. Alternatively use AudioFileReader instead of WaveFileReader and again you can access a version of the Read method that fills a float[]
16-bit PCM is an signed-integer encoding. Presuming you want doubles between 0 and 1, you simply read each sample as an 16-bit signed integer, and then divide by (double)32768.0;
var floatSamples = new double[read/2];
for(int sampleIndex = 0; sampleIndex < read/2; sampleIndex++) {
var intSampleValue = BitConverter.ToInt16(bytesBuffer, sampleIndex*2);
floatSamples[sampleIndex] = intSampleValue/32768.0;
}
Note that stereo channels are interleaved (left sample, right sample, left sample, right sample).
There's some good info on the format here: http://blog.bjornroche.com/2013/05/the-abcs-of-pcm-uncompressed-digital.html
I've been trying to get my program to replace unicode in a binary file.
The user would input what to find, and the program would find and replace it with a specific string if it can find it.
I've searched around, but there's nothing I can find to my specifics, what I would like would be something like:
string text = File.ReadAllText(path, Encoding.Unicode);
text = text.Replace(userInput, specificString);
File.WriteAllText(path, text);
but anything that works in a similar manner should suffice.
Using that results in a file that is larger and unusable, though.
I use:
int var = File.ReadAllText(path, Encoding.Unicode).Contains(userInput) ? 1 : 0;
if (var == 1)
{
//Missing Part
}
for checking if the file contains the user inputted string, if it matters.
This can work only in very limited situations. Unfortunately, you haven't offered enough details as to the nature of the binary file for anyone to know if this will work in your situation or not. There are a practically endless variety of binary file formats out there, at least some of which would be rendered invalid if you modify a single byte, many more of which could be rendered invalid if the file length changes (i.e. data after your insertion point is no longer where it is expected to be).
Of course, many binary files are also either encrypted, compressed, or both. In such cases, even if you do by some miracle find the text you're looking for, it probably doesn't actually represent that text, and modifying it will render the file unusable.
All that said, for the sake of argument let's assume your scenario doesn't have any of these problems and it's perfectly okay to just completely replace some text found in the middle of the file with some entirely different text.
Note that we also need to make an assumption about the text encoding. Text can be represented in a wide variety of ways, and you will need to use the correct encoding not just to find the text, but also to ensure the replacement text will be valid. For the sake of argument, let's say your text is encoded as UTF8.
Now we have everything we need:
void ReplaceTextInFile(string fileName, string oldText, string newText)
{
byte[] fileBytes = File.ReadAllBytes(fileName),
oldBytes = Encoding.UTF8.GetBytes(oldText),
newBytes = Encoding.UTF8.GetBytes(newText);
int index = IndexOfBytes(fileBytes, oldBytes);
if (index < 0)
{
// Text was not found
return;
}
byte[] newFileBytes =
new byte[fileBytes.Length + newBytes.Length - oldBytes.Length];
Buffer.BlockCopy(fileBytes, 0, newFileBytes, 0, index);
Buffer.BlockCopy(newBytes, 0, newFileBytes, index, newBytes.Length);
Buffer.BlockCopy(fileBytes, index + oldBytes.Length,
newFileBytes, index + newBytes.Length,
fileBytes.Length - index - oldBytes.Length);
File.WriteAllBytes(filename, newFileBytes);
}
int IndexOfBytes(byte[] searchBuffer, byte[] bytesToFind)
{
for (int i = 0; i < searchBuffer.Length - bytesToFind.Length; i++)
{
bool success = true;
for (int j = 0; j < bytesToFind.Length; j++)
{
if (searchBuffer[i + j] != bytesToFind[j])
{
success = false;
break;
}
}
if (success)
{
return i;
}
}
return -1;
}
Notes:
The above is destructive. You may want to run it only on a copy of the file, or prefer to modify the code so that it takes an addition parameter specifying the new file to which the modification should be written.
This implementation does everything in-memory. This is much more convenient, but if you are dealing with large files, and especially if you are on a 32-bit platform, you may find you need to process the file in smaller chunks.
I have a requirement to test some load issues with regards to file size. I have a windows application written in C# which will automatically generate the files. I know the size of each file, ex. 100KB, and how many files to generate. What I need help with is how to generate a string less than or equal to the required file size.
pseudo code:
long fileSizeInKB = (1024 * 100); //100KB
int numberOfFiles = 5;
for(var i = 0; i < numberOfFiles - 1; i++) {
var dataSize = fileSizeInKB;
var buffer = new byte[dataSize];
using (var fs = new FileStream(File, FileMode.Create, FileAccess.Write)) {
}
}
You can always use the a constructor for string which takes a char and a number of times you want that character repeated:
string myString = new string('*', 5000);
This gives you a string of 5000 stars - tweak to your needs.
Easiest way would be following code:
var content = new string('A', fileSizeInKB);
Now you've got a string with as many A as required.
To fill it with Lorem Ipsum or some other repeating string build something like the following pseudocode:
string contentString = "Lorem Ipsum...";
for (int i = 0; i < fileSizeInKB / contentString.Length; i++)
//write contentString to file
if (fileSizeInKB % contentString.Length > 0)
// write remaining substring of contentString to file
Edit: If you're saving in Unicode you may need to half the filesize count because unicode uses two bytes per character if I remember correctly.
There are so many variations on how you can do this. One would be, fill the file with a bunch of chars. You need 100KB? No problem.. 100 * 1024 * 8 = 819200 bits. A single char is 16 bits. 819200 / 16 = 51200. You need to stick 51,200 chars into a file. But consider that a file may have additional header/meta data, so you may need to account for that and decrease the number of chars to write to file.
As a partial answer to your question I recently created a portable WPF app that easily creates 'junk' files of almost any size: https://github.com/webmooch/FileCreator