C# unique file naming with String from Streamreader - c#

ok i have solved my problem of finding a unique word within the file that is then used as the newly created .txt file name.
for example: current.txt files have 200 lines of words/data per file but one of the words is unique("92222225") with every current.txt file.
so the newly created output files from streamwriter becomes 92222225.txt, 933333334.txt and so on.
the whole time i though what i needed was within streamreader or streamwriter.
but what i need to add to the two was "Regex.Match".
here is the code i figured out to use for pulling strings out of a .txt file to use as a name for the output files. also to add other words to the new output file.
string mydocpath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\reporting";
foreach (string txtName in Directory.EnumerateFiles(mydocpath, "*.txt"))
{
StringBuilder sb = new StringBuilder();
StreamReader sr = new StreamReader(txtName);
string content = sr.ReadToEnd();
sb.AppendLine(txtName.ToString());
sb.AppendLine("= = = = = =");
sb.Append(content);
if (content.Contains("helloworld"))
{
sb.AppendLine();
sb.AppendLine("byeworld");
}
sb.AppendLine();
sb.AppendLine();
//string fileName = content.Contains("helloworld").ToString();
string FindMatch = content;
Match match = Regex.Match(FindMatch, #"9(([A-Za-z0-9\-])\d+)");
if (match.Success)
{
//this is what adds unique word as 922225.txt file name.
string capture = match.Groups[1].Captures[0].Value;
using (StreamWriter outfile = new StreamWriter(mydocpath + #"\" + capture + ".txt"))
{
outfile.Write(sb.ToString());
}
}
}
i updated this whole post so if anyone else may need this.
never even used Regex.Match before, nor knew about it or maybe i forgot about it.

If you want to name your output file use:
using (StreamWriter outfile = new StreamWriter(mydocpath + #"\901232lOi.txt"))

Related

How to remove last characters from a string

So I am writing a C# program which combines several text files into one and saves them as a combined text file. One issue I am having, I have a textfield which selects the intended folder the save the compiled reciept, however when selecting the desired folder, it generates a file name to the text box, the filename follwing the final / must be erased every time for the save function to work properly. I am wondering, how to remove all text after the final letter before the last / in the file directory?
Here is the code:
private void RecieptDisplayed_TextChanged(object sender, EventArgs e)
{
try
{
string[] fileAry = Directory.GetFiles(RecieptSelect.Text);
string input = RecieptSelect.Text;
int index = input.LastIndexOf("/");
if (index >= 0)
input = input.Substring(0, index);
MessageBox.Show("Reciepts being processed : " + index);
using (TextWriter tw = new StreamWriter(savefileas.Text + "RecieptsCombined.txt", true))
{
foreach (string filePath in fileAry)
{
using (TextReader tr = new StreamReader(filePath))
{
tw.WriteLine("Reciept for: " + " " + filePath + tr.ReadToEnd()) ;
tr.Close();
tr.Dispose();
}
MessageBox.Show("File Processed : " + filePath);
}
tw.Close();
tw.Dispose();
}
}
You have a string like
var fullpath = #"C:\temp\myfile.txt";
You can use:
var dir = Path.GetDirectoryName(fullpath);
To get
c:\temp
Note that if the path ends with a slash it doesn't remove it before "going up a directory" so c:\temp\ becomes c:\temp. Try to keep your paths free of trailing slashes
Try to always use the Path class when manipulating string that are paths. It has a whole load of useful methods (this isn't an exhaustive list but the ones I use most) like:
GetFileName
GetFileNameWithoutExtension
GetExtension
ChangeExtension
Combine
This last one builds paths, eg:
Path.Combine("c:", "temp", "myfile.txt");
It knows the different operating systems it runs on and builds paths appropriately - if you're using net core on Linux it uses "/" instead of "\" for example. full docs here
Construct a FileInfo object from the string and then use DirectoryName or Directory.
Also, do not concatenate strings to get a file name, use Path.Combine instead.
You are looking for Directory name from given path, you can use existing function to get the directory name, Path.GetDirectoryName()
using System.IO;
...
//Get the directory name
var directoryName = Path.GetDirectoryName(savefileas.Text);
using (TextWriter tw = new StreamWriter(Path.Combine(directoryName, "RecieptsCombined.txt"), true))
{
foreach (string filePath in fileAry)
{
using (TextReader tr = new StreamReader(filePath))
{
tw.WriteLine("Reciept for: " + " " + filePath + tr.ReadToEnd()) ;
tr.Close();
tr.Dispose();
}
MessageBox.Show("File Processed : " + filePath);
}
tw.Close();
tw.Dispose();
}

C# How to use a folder in a project

I've honestly been researching about this for hours, and I still haven't found anything close to what I am looking for.
Basically I created a folder in my project and called it "Files". Then I added a lot of actual files to that folder, and now I want to access them via a void, but I can't get the names of them.
I've tried to display the files in a message box (just for testing purposes), so I used this:
public static string[] GetResourceNames()
{
var asm = Assembly.GetEntryAssembly();
string resName = asm.GetName().Name + ".Files";
using (var stream = asm.GetManifestResourceStream(resName))
using (var reader = new System.Resources.ResourceReader(stream))
{
return reader.Cast<DictionaryEntry>().Select(entry => (string)entry.Key).ToArray();
}
}
But all it does is return an error saying the reader can't be null.
I'm trying to show it in a foreach loop like this:
foreach (string resourceName in GetResourceNames())
{
MessageBox.Show(resourceName);
}
but it shows nothing.
What I'm trying to do is this:
Assembly assembly = Assembly.GetExecutingAssembly();
int totalFiles = 17;
int currentFiles = 0;
foreach (var file in assembly.GetManifestResourceNames())
{
string extractPath = functions.pathToExtract + #"\" + file;
using (Stream s = assembly.GetManifestResourceStream(file))
using (BinaryReader r = new BinaryReader(s))
using (FileStream fs = new FileStream(extractPath, FileMode.OpenOrCreate))
using (BinaryWriter w = new BinaryWriter(fs))
w.Write(r.ReadBytes((int)s.Length));
currentFile.Invoke((MethodInvoker)delegate { currentFile.Text = "Installing : " + file + " ( " + currentFiles + " out of "+ totalFiles + " installed )"; });
currentFiles += 1;
}
This is what I'm trying to do, and this is code is successful, but it writes the file names as: SolutionName.Files.FileName.Extension and I only want it to write as FileName.Extension
What am I doing wrong here?
Well, a resource file is stored with the format you've specified: [Solution].[Folder].[File].[Extension].
Assuming all you really want to do is remove the initial [Solution].[Folder] from file names you can just use String.Replace.
Something like:
var fileName = file.Replace("[Solution].[Folder]", "");
Then use fileName for the currentFile.Text or for extractPath. Be mindful that I don't know what functions.pathToExtract + #"\" + file in your code produces at the moment, so it's a bit of a guess on my part, but I think this would produce a sensible path which could be used for extracting embedded resources.

SSIS remove carriage returns

I've a flat file which has 48 columns. The columns are tab delimited and the rows CR-LF (return).
Now I've the problem that there is a column which sometimes contains carriage returns and there is no possibility to change the file before the import process.
At the moment I wrote a C# script task which looks in every row, counts the tabs and when there is a return and the counted tabs are not divisible by 48 it deletes the return. This way works but it's to slow because my files are very big and with that way I've to read every character in the file.
Does someone knows a better way to get rid of these carriage returns?
Cheers!
https://community.spiceworks.com/topic/2130093-ssis-package-flat-file-destination-blank-row-at-end-of-file
public void Main()
{
string filename = #"C:\Temp\Gerard.txt";
string fileinfo = "";
string curline = "";
TextReader tr = new StreamReader(filename);
while ((curline = tr.ReadLine()) != null)
{
if (fileinfo != "")
{
fileinfo = fileinfo + Environment.NewLine;
}
fileinfo = fileinfo + curline;
}
tr.Close();
TextWriter tw = new StreamWriter(filename, false);
tw.Write(fileinfo);
tw.Close();
Dts.TaskResult = (int)ScriptResults.Success;
}

File cannot be accessed because it is being used by another program

I am trying to remove the space at the end of line and then that line will be written in another file.
But when the program reaches to FileWriter then it gives me the following error
Process can't be accessed because it is being used by another process.
The Code is as below.
private void FrmCounter_Load(object sender, EventArgs e)
{
string[] filePaths = Directory.GetFiles(#"D:\abc", "*.txt", SearchOption.AllDirectories);
string activeDir = #"D:\dest";
System.IO.StreamWriter fw;
string result;
foreach (string file in filePaths)
{
result = Path.GetFileName(file);
System.IO.StreamReader f = new StreamReader(file);
string newFileName = result;
// Combine the new file name with the path
string newPath = System.IO.Path.Combine(activeDir, newFileName);
File.Create(newPath);
fw = new StreamWriter(newPath);
int counter = 0;
int spaceAtEnd = 0;
string line;
// Read the file and display it line by line.
while ((line = f.ReadLine()) != null)
{
if (line.EndsWith(" "))
{
spaceAtEnd++;
line = line.Substring(0, line.Length - 1);
}
fw.WriteLine(line);
fw.Flush();
counter++;
}
MessageBox.Show("File Name : " + result);
MessageBox.Show("Total Space at end : " + spaceAtEnd.ToString());
f.Close();
fw.Close();
}
}
File.Create itself returns a stream.
Use that stream to write file. Reason you are receiving this error is because Stream returned by File.Create is open and you are trying to open that file again for write.
Either close the stream returned by File.Create or better use that stream for file write or use
Stream newFile = File.Create(newPath);
fw = new StreamWriter(newFile);
Even though you solved your initial problem, if you want to write everything into a new file in the original location, you can try to read all of the data into an array and close the original StreamReader. Performance note: If your file is sufficiently large though, this option is not going to be the best for performance.
And you don't need File.Create as the StreamWriter will create a file if it doesn't exist, or overwrite it by default or if you specify the append parameter as false.
result = Path.GetFileName(file);
String[] f = File.ReadAllLines(file); // major change here...
// now f is an array containing all lines
// instead of a stream reader
using(var fw = new StreamWriter(result, false))
{
int counter = f.Length; // you aren't using counter anywhere, so I don't know if
// it is needed, but now you can just access the `Length`
// property of the array and get the length without a
// counter
int spaceAtEnd = 0;
// Read the file and display it line by line.
foreach (var item in f)
{
var line = item;
if (line.EndsWith(" "))
{
spaceAtEnd++;
line = line.Substring(0, line.Length - 1);
}
fw.WriteLine(line);
fw.Flush();
}
}
MessageBox.Show("File Name : " + result);
MessageBox.Show("Total Space at end : " + spaceAtEnd.ToString());
Also, you will not remove multiple spaces from the end of the line using this method. If you need to do that, consider replacing line = line.Substring(0, line.Length - 1); with line = line.TrimEnd(' ');
You have to close any files you are reading before you attempt to write to them in your case.
Write stream in using statement like:
using (System.IO.StreamReader f = new StreamReader(file))
{
//your code goes here
}
EDIT:
Zafar is correct, however, maybe this will clear things up.
Because File.Create returns a stream.. that stream has opened your destination file. This will make things clearer:
File.Create(newPath).Close();
Using the above line, makes it work, however, I would suggest re-writing that properly. This is just for illustrative purposes.

C# comparing two files regex problem

what I'm trying to do is open a huge list of files (about 40k records, and match them on a line in a file that contains 2 millions records. And if my line from file A matches a line in file B write out that line.
File A contains a bunch of files without extensions and file B contains full file paths including extensions.
i'm using this but i cant get it to go...
string alphaFilePath = (#"C:\Documents and Settings\g\Desktop\Arrp\Find\natst_ready.txt");
List<string> alphaFileContent = new List<string>();
using (FileStream fs = new FileStream(alphaFilePath, FileMode.Open))
using (StreamReader rdr = new StreamReader(fs))
{
while (!rdr.EndOfStream)
{
alphaFileContent.Add(rdr.ReadLine());
}
}
string betaFilePath = #"C:\Documents and Settings\g\Desktop\Arryup\Find\eble.txt";
StringBuilder sb = new StringBuilder();
using (FileStream fs = new FileStream(betaFilePath, FileMode.Open))
using (StreamReader rdr = new StreamReader(fs))
{
while (!rdr.EndOfStream)
{
string betaFileLine = rdr.ReadLine();
string matchup = Regex.Match(alphaFileContent, #"(\\)(\\)(\\)(\\)(\\)(\\)(\\)(\\)(.*)(\.)").Groups[9].Value;
if (alphaFileContent.Equals(matchup))
{
File.AppendAllText(#"C:\array_tech.txt", betaFileLine);
}
}
}
This doesnt work because the alphafilecontent is a single line only and i'm having a hard time figuring out how to get my regex to work on the file that contains all the file paths (Betafilepath)
here is a sample of the beta file path.
C:\arres_i\Grn\Ora\SEC\DBZ_EX1\Nes\001\DZO-EX00001.txt
Here is the line i'm trying to compare from my alpha
DZO-EX00001
Use System.IO.Path.GetFileNameWithoutExtension instead of a regular expression.
static void Compare(string alpha, string beta)
{
HashSet<string> alphaContent = new HashSet<string>();
StreamReader reader = new StreamReader(alpha);
while (!reader.EndOfStream)
alphaContent.Add(reader.ReadLine());
reader.Close();
reader = new StreamReader(beta);
while (!reader.EndOfStream)
{
string fullpath = reader.ReadLine();
string filename = Path.GetFileNameWithoutExtension(fullpath);
if (alphaContent.Contains(filename))
{
File.AppendAllText(#"C:\array_tech.txt", fullpath);
}
}
reader.Close();
}
So, you read in all the lines in beta, and have the whole thing stored in a string, beta.
Next, you read a line from alpha and have DZO-EX00001 stored in a string, alpha.
var pattern = #"^.*" + alpha + ".*$";
var match = Regex.Match(beta, pattern, RegexOptions.Multiline);
if(match.Success)
{
string filepath = match.Value;
// do stuff
}
You need to load all of the lines from beta first. Then you can check each line from alpha against it.
You must specify RegexOptions.Multiline to check against all the lines in beta (so that the ^ and $ will match at each line instead of at the beginning and end of the whole string.
The pattern can be expanded if you need to be more specific; as is, it just gets the first line that contains the filename.

Categories