I am trying to convert a part of a .txt file to TIFF image, as
public static void ReadTextFileLineByLine(string fileName)//fileName- "c:\\test.txt"
{
int counter = 0;
string line;
List<string> linelist = new List<string>();
System.IO.StreamReader file = new System.IO.StreamReader(strFileName);
while ((line = file.ReadLine()) != null && counter!=19)
{
linelist.Add(line);
counter++;
}
file.Close();
ConvertlistToByteArrayToTiff(linelist);
}
public static void ConvertlistToByteArrayToTiff(List<string> list)
{
byte[] dataAsBytes = list
.SelectMany(s => System.Text.Encoding.ASCII.GetBytes(s))
.ToArray();
MemoryStream ms = new MemoryStream(dataAsBytes);
Image returnImage = Image.FromStream(ms);
returnImage.Save("c:\\133.tiff", System.Drawing.Imaging.ImageFormat.Tiff);
}
I am getting error at Image.FromStream(ms);:
Parameter is not valid.
Is my approach correct or I need to do it in different way?
Is my approach correct
No
or I need to do it in different way?
Yes
You can "print"/draw the text to an image. Like shown here: https://stackoverflow.com/a/6311628/2655508
Your assumption, that a tiffs (or any other image) representation of text, is just the ascii value of the chars isn't correct.
To read about Tiff: http://en.wikipedia.org/wiki/Tagged_Image_File_Format
To understand the structure of Tiff: See RFC 2306
Related
In my project I am using this code to insert image to database
private void pctbPicture_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog1 = new OpenFileDialog())
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var filename = openFileDialog1.FileName;
var file = File.ReadAllBytes(filename);
// request.Image is byte[]
request.Image = file;
Image image = Image.FromFile(filename);
pctbProizvod.Image = image;
}
}
}
In my database when i try to check value of Image it only says byte array
But when i get data from swagger api i can see huge string of letters and numbers as value of image.
Now i am making dataseding script with test data and i would like to insert data from that string of numbers and letters as byte array in database.
something like this pseudocode
Product pp=new Product(){Image = ConverToByteArray(string that represents byte aray From Swagger) };
any help is appreciated!!
Thanks for trying to help
Solution in my case was
Image= Convert.FromBase64String("string content");
I want to count the number of some strings and store it into a csv file. I've tried it but I don't know if this is the correct way and in addition, there are two problems.
First of all, here is my method:
public void CountMacNames(String macName)
{
string path = #"D:\Counter\macNameCounter.csv";
if (!File.Exists(path))
{
File.Create(path).Close();
}
var lines = File.ReadLines(path);
foreach (var line in lines)
{
bool isExists = line.Split(',').Any(x => x == macName);
if (isExists)
{
// macName exists, increment it's value by 1
}
else
{
// macName does not exists, add macName to CSV file and start counter by 1
var csv = new StringBuilder();
var newLine = string.Format("{0},{1}", macName, 1);
csv.AppendLine(newLine);
File.WriteAllText(path, csv.ToString());
}
}
}
The first problem is this IOException:
The process cannot access the file 'D:\Counter\macNameCounter.csv'
because it is being used by another process.
The second problem is, that I don't know how to increment the value by one, if a macName exists in the csv file (see first comment)
EDIT: Example for method "CountMacNames" call:
CountMacNames("Cansas");
CountMacNames("Wellback");
CountMacNames("Newton");
CountMacNames("Cansas");
CountMacNames("Princet");
Then, the CSV file should contain:
Cansas, 2
Wellback, 1
Newton, 1
Princet, 1
OK, this is what I'd do:
public void CountMacNames(String macName)
{
string path = #"D:\Counter\macNameCounter.csv";
// Read all lines, but only if file exists
string[] lines = new string[0];
if (File.Exists(path))
lines = File.ReadAllLines(path);
// This is the new CSV file
StringBuilder newLines = new StringBuilder();
bool macAdded = false;
foreach (var line in lines)
{
string[] parts = line.Split(',');
if (parts.Length == 2 && parts[0].Equals(macName))
{
int newCounter = Convert.ToIn32(parts[1])++;
newLines.AppendLine(String.Format("{0},{1}", macName, newCounter));
macAdded = true;
}
else
{
newLines.AppendLine(line.Trim());
}
}
if (!macAdded)
{
newLines.AppendLine(String.Format("{0},{1}", macName, 1));
}
File.WriteAllText(path, newLines.ToString());
}
This code does this:
Read all the lines from file only if it exists - otherwise we start a new file
Iterate over all the lines
If the first part of a 2-part line equals the mac, add 1 to counter and add line to output
If the first part doesn't match or the line format is wrong, add the line to output as is
If we didn't find the mac in any line, add a new line for the mac with counter 1
Write the file back
You can't read and write to the same file at the same time (in a simple way).
For small files, there are already answers.
If your file is really large (too big to fit in memory) you need another approach:
Read input file line by line
optinally modify the current line
write line to a temporary file
If finished delete input file, rename temporary file
For the first problem you can either read all the lines into memory and work there then write it all out again, or use streams.
using (FileStream fs = File.Open(filePath, FileMode.Create, FileAccess.ReadWrite))
{
var sw = new StreamWriter(fs);
var sr = new StreamReader(fs);
while(!streamReader.EndOfStream)
{
var line = sr.ReadLine();
//Do stuff with line.
//...
if (macExists)
{
//Increment the number, Note that in here we can only replace characters,
//We can't insert extra characters unless we rewrite the rest of the file
//Probably more hassle than it's worth but
//You could have a fixed number of characters like 000001 or 1
//Read the number as a string,
//Int.Parse to get the number
//Increment it
//work out the number of bytes in the line.
//get the stream position
//seek back to the beginning of the line
//Overwrite the whole line with the same number of bytes.
}
else
{
//Append a line, also harder to do with streams like this.
//Store the current position,
//Seek to the end of the file,
//WriteLine
//Seek back again.
}
}
}
You need to read the file in and release it, like this, to avoid the IO exception:
string[] lines = null;
using (var sr = new System.IO.StreamReader(path))
lines = sr.ReadToEnd().Split(new string[] {"\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);
As for the count, you can just add an int value, change the method return type as int, too.
public int CountMacNames(String macName, String path)
{
if (!File.Exists(path))
{
File.Create(path).Close();
}
string[] lines = null;
using (var sr = new System.IO.StreamReader(path))
lines = sr.ReadToEnd().Split(new string[] {"\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);
return lines.Where(p => p.Split(',').Contains(macName)).Count();
}
and inside the method that calls it:
var path = #"<PATH TO FILE>";
var cnt = CountMacNames("Canvas", path);
if (cnt > 0)
{
using (var sw = new StreamWriter(path, true, Encoding.Unicode))
sw.WriteLine(string.Format("Canvas,{0}", cnt));
}
Now, var res = CountMacNames("Canvas","PATH"); will return 2, and the lines "Canvas,2" or "Newton,1" will be appended to the file, without overwriting it.
I'm trying to insert images in my rich text box in C#, but so far I'm only failing. Miserably.
This is the code that I am using:
Clipboard.SetImage(Image.FromFile(Application.StartupPath + #"\PIC\" + i + ".bmp"));
chat.Paste();
The real problem is I am not able to put both text and image in the textbox. The moment I insert text after copying the image the image disappears. I am unable to find a solution for this
Can anybody help me with this? Please???
Thanks
RichTextBox rtb = new RichTextBox();
byte[] headerImage = (byte[])(dr["ImageData"]);
string imageData = string.Empty;
if (headerImage != null && headerImage.Length > 0)
{
Bitmap bmp = new Bitmap(new MemoryStream(headerImage));
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Position = 0;
imageData = #"{\pict\jpegblip\picw10449\pich3280\picwgoal9924\pichgoal1860\ " + BitConverter.ToString(ms.ToArray()).Replace("-", string.Empty).ToLower() + "}";
ms.Dispose();
}
string finalrtfdata = rtb.Rtf;
finalrtfdata = finalrtfdata.Replace("&ImageHeader&", imageData);
// finalrtfdata contain your image data along with rtf tags.
Try this out,you can paste this into your code and call it:
place a picture into your project to embeded resource,and call this method
passing the richtextbox.
private void createImage(Control item)
{
Hashtable image = new Hashtable(1);
image.Add(item,yourproject.Properties.Resources.yourpicturename);
Clipboard.SetImage((Image)image[item]);
((RichTextBox)item).Paste();
}
private static void createImage(RichTextBox item)
{
var image = new Hashtable(1) { { item, Properties.Resources.yourimage } };
Clipboard.SetImage((Image)image[item]);
item.Paste();
}
I thought I am writing 10 file extensions and their related Icons as Bitmap into a resource file within a for loop. The odd thing is that only the last file extension with its Icon is written into the Resource.resx file. Somehow the next file extension in the loop is overwriting the previous one, but WHY ? I thought a resource is sort of a dictionary with key/value pair where I can add as much as I want just as I do in the Resource designer...
What do I wrong?
My code:
private void AddDocument()
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Multiselect = true;
DialogResult result = fileDialog.ShowDialog();
if (result == DialogResult.OK)
{
for (int i = 0; i < fileDialog.FileNames.Length; i++)
{
string absoluteFilePath = fileDialog.FileNames.GetValue(i).ToString();
byte[] file = File.ReadAllBytes(absoluteFilePath);
String fileExtension = Path.GetExtension(absoluteFilePath);
Bitmap gdiImage;
Document doc = new Document();
doc.DocumentData = file;
doc.DocumentName = fileDialog.SafeFileNames.GetValue(i).ToString();
if (TryIsFileExtensionExisting(fileExtension, out gdiImage))
{
// Filetype was saved before => Convert GDI Bitmap to wpf BitmapImage
doc.DocumentTypeImage = gdiImage.ConvertGDIImageToWPFBitmapImage();
}
else
{
BitmapImage wpfImage;
// Filetype is new => get Bitmap out of the Icon
Icon icon = IconFromFilePath(absoluteFilePath);
Bitmap bitmap = icon.ToBitmap();
wpfImage = bitmap.ConvertGDIImageToWPFBitmapImage();
doc.DocumentTypeImage = wpfImage;
// Save bitmap to resource
using (ResXResourceWriter writer = new ResXResourceWriter("TBM.Resource"))
{
writer.AddResource(fileExtension, bitmap);
writer.Generate();
}
}
DocumentList.Add(doc);
}
_documentService.AddDocumentsToPeriod(DocumentList, _parentId);
}
}
private bool TryIsFileExtensionExisting(String fileExtension, out Bitmap wpfImage)
{
DictionaryEntry entry;
using (ResXResourceReader reader = new ResXResourceReader ("TBM.Resource"))
{
entry = reader.Cast<DictionaryEntry>()
.Where(x => x.Key.ToString()
.Equals(fileExtension, StringComparison.CurrentCultureIgnoreCase))
.FirstOrDefault();
};
wpfImage = entry.Value as Bitmap;
return entry.Key != null;
}
private Icon IconFromFilePath(string filePath)
{
Icon result = null;
try
{
result = Icon.ExtractAssociatedIcon(filePath);
//'# swallow and return nothing. You could supply a default Icon here as well
}
catch
{
}
return result;
}
The problem is here:
using (ResXResourceWriter writer = new ResXResourceWriter("TBM.Resource"))
{
writer.AddResource(fileExtension, bitmap);
writer.Generate();
}
Each time you create a new writer object and write to it. But you don't have the creation of the writer object read from the old file. So you overwrite every time. You should be able to use a different constructor and solve your problem.
http://msdn.microsoft.com/en-us/library/system.resources.resxresourcewriter.aspx
I have two text files, Source.txt and Target.txt. The source will never be modified and contain N lines of text. So, I want to delete a specific line of text in Target.txt, and replace by an specific line of text from Source.txt, I know what number of line I need, actually is the line number 2, both files.
I haven something like this:
string line = string.Empty;
int line_number = 1;
int line_to_edit = 2;
using StreamReader reader = new StreamReader(#"C:\target.xml");
using StreamWriter writer = new StreamWriter(#"C:\target.xml");
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
writer.WriteLine(line);
line_number++;
}
But when I open the Writer, the target file get erased, it writes the lines, but, when opened, the target file only contains the copied lines, the rest get lost.
What can I do?
the easiest way is :
static void lineChanger(string newText, string fileName, int line_to_edit)
{
string[] arrLine = File.ReadAllLines(fileName);
arrLine[line_to_edit - 1] = newText;
File.WriteAllLines(fileName, arrLine);
}
usage :
lineChanger("new content for this line" , "sample.text" , 34);
You can't rewrite a line without rewriting the entire file (unless the lines happen to be the same length). If your files are small then reading the entire target file into memory and then writing it out again might make sense. You can do that like this:
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
int line_to_edit = 2; // Warning: 1-based indexing!
string sourceFile = "source.txt";
string destinationFile = "target.txt";
// Read the appropriate line from the file.
string lineToWrite = null;
using (StreamReader reader = new StreamReader(sourceFile))
{
for (int i = 1; i <= line_to_edit; ++i)
lineToWrite = reader.ReadLine();
}
if (lineToWrite == null)
throw new InvalidDataException("Line does not exist in " + sourceFile);
// Read the old file.
string[] lines = File.ReadAllLines(destinationFile);
// Write the new file over the old file.
using (StreamWriter writer = new StreamWriter(destinationFile))
{
for (int currentLine = 1; currentLine <= lines.Length; ++currentLine)
{
if (currentLine == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
writer.WriteLine(lines[currentLine - 1]);
}
}
}
}
}
If your files are large it would be better to create a new file so that you can read streaming from one file while you write to the other. This means that you don't need to have the whole file in memory at once. You can do that like this:
using System;
using System.IO;
class Program
{
static void Main(string[] args)
{
int line_to_edit = 2;
string sourceFile = "source.txt";
string destinationFile = "target.txt";
string tempFile = "target2.txt";
// Read the appropriate line from the file.
string lineToWrite = null;
using (StreamReader reader = new StreamReader(sourceFile))
{
for (int i = 1; i <= line_to_edit; ++i)
lineToWrite = reader.ReadLine();
}
if (lineToWrite == null)
throw new InvalidDataException("Line does not exist in " + sourceFile);
// Read from the target file and write to a new file.
int line_number = 1;
string line = null;
using (StreamReader reader = new StreamReader(destinationFile))
using (StreamWriter writer = new StreamWriter(tempFile))
{
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
writer.WriteLine(line);
}
line_number++;
}
}
// TODO: Delete the old file and replace it with the new file here.
}
}
You can afterwards move the file once you are sure that the write operation has succeeded (no excecption was thrown and the writer is closed).
Note that in both cases it is a bit confusing that you are using 1-based indexing for your line numbers. It might make more sense in your code to use 0-based indexing. You can have 1-based index in your user interface to your program if you wish, but convert it to a 0-indexed before sending it further.
Also, a disadvantage of directly overwriting the old file with the new file is that if it fails halfway through then you might permanently lose whatever data wasn't written. By writing to a third file first you only delete the original data after you are sure that you have another (corrected) copy of it, so you can recover the data if the computer crashes halfway through.
A final remark: I noticed that your files had an xml extension. You might want to consider if it makes more sense for you to use an XML parser to modify the contents of the files instead of replacing specific lines.
When you create a StreamWriter it always create a file from scratch, you will have to create a third file and copy from target and replace what you need, and then replace the old one.
But as I can see what you need is XML manipulation, you might want to use XmlDocument and modify your file using Xpath.
You need to Open the output file for write access rather than using a new StreamReader, which always overwrites the output file.
StreamWriter stm = null;
fi = new FileInfo(#"C:\target.xml");
if (fi.Exists)
stm = fi.OpenWrite();
Of course, you will still have to seek to the correct line in the output file, which will be hard since you can't read from it, so unless you already KNOW the byte offset to seek to, you probably really want read/write access.
FileStream stm = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
with this stream, you can read until you get to the point where you want to make changes, then write. Keep in mind that you are writing bytes, not lines, so to overwrite a line you will need to write the same number of characters as the line you want to change.
I guess the below should work (instead of the writer part from your example). I'm unfortunately with no build environment so It's from memory but I hope it helps
using (var fs = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite)))
{
var destinationReader = StreamReader(fs);
var writer = StreamWriter(fs);
while ((line = reader.ReadLine()) != null)
{
if (line_number == line_to_edit)
{
writer.WriteLine(lineToWrite);
}
else
{
destinationReader .ReadLine();
}
line_number++;
}
}
The solution works fine. But I need to change single-line text when the same text is in multiple places. For this, need to define a trackText to start finding after that text and finally change oldText with newText.
private int FindLineNumber(string fileName, string trackText, string oldText, string newText)
{
int lineNumber = 0;
string[] textLine = System.IO.File.ReadAllLines(fileName);
for (int i = 0; i< textLine.Length;i++)
{
if (textLine[i].Contains(trackText)) //start finding matching text after.
traced = true;
if (traced)
if (textLine[i].Contains(oldText)) // Match text
{
textLine[i] = newText; // replace text with new one.
traced = false;
System.IO.File.WriteAllLines(fileName, textLine);
lineNumber = i;
break; //go out from loop
}
}
return lineNumber
}