C# Problem incrementing a file name when the file name already exists - c#

File name format = 123456.1.pdf
Example:
Entered 123456 in the textbox. If a file by that number exists the program would increment the number to 123456.1
Entered 123456.1 in the textbox. If a file by that number exists the program would increment the number to 123456.2
Entered 123456.11 in the textbox. If a file by that number exists the program would increment the number to 123456.12
Problem is when 123456.9 exists, the program increments it to 123456.110 or 123456.1111 What am I doing wrong? Thank you for your help.
MyWO = WO.Text;
string plusOne = MyWO.Substring(MyWO.Length - 1);
string FnlName;
int cnt;
if (MyWO.Length == 8 ) { cnt = Convert.ToInt32(plusOne) + 1; }
else { cnt = 1; }
while (File.Exists(savePath + MyWO + ".pdf"))
{
if (MyWO.Length == 6)
{
FnlName = (MyWO + "." + cnt.ToString());
}
else
{
string Fnl = MyWO.Remove(MyWO.Length - 1, 1);
FnlName = (Fnl + cnt.ToString());
}
cnt++;
}

The issue is that you're only using strings of length 6 or 8. Once you get two digits after the decimal your string is now 9 characters and your code doesn't like that.
The answer is to not work with fixed lengths and let the code work it out.
Here's how:
int number = 0;
int version = 1;
string filename = "";
MyWO = WO.Text;
var parts = MyWO.Split('.');
if (parts.Length <= 2
&& int.TryParse(parts[0], out number)
&& (parts.Length == 1 || int.TryParse(parts[1], out version)))
{
while (File.Exists(filename = Path.Combine(savePath, $"{number}.{version}.pdf")))
{
version++;
}
/*
Do something here with the `filename`
*/
}
else
{
Console.WriteLine("Bad user input");
}

I suggest a simple for loop: we can try i = 0, 1, 2, ... until we find fileName that's no existing:
string name = WO.Text;
string fileName = null;
for (int i = 0; ; ++i) {
fileName = $"{name}{(i == 0 ? "" : "." + i.ToString())}.pdf";
if (!File.Exists(Path.Combine(savePath, fileName)))
break;
}
// now fileName is a non-existing file name in "name.index.pdf" format
// Path.Combine(savePath, fileName) - complete file name

Something like this ought to do you:
public static string GenerateFileName( string fn )
{
Match m = rxFileNamePattern.Match(fn) ;
if (!m.Success) throw new Exception("Invalid name") ;
string pfx = m.Groups["pfx"].Value ;
int sfx = int.Parse( m.Groups["sfx"].Value ) ;
string ext = m.Groups["ext"].Value ;
string nextName = fn ;
bool exists ;
while ( (exists=File.Exists(nextName)) )
{
nextName = string.Format( "{0}{1}{2}", pfx, sfx, ext ) ;
}
return nextName;
}
const RegexOptions rxOptions = RegexOptions.IgnoreCase
| RegexOptions.IgnorePatternWhitespace
;
private static readonly Regex rxFileNamePattern = new Regex(#"
^ # start-of-text, followed by
(?<pfx>[0-9]+[.])? # an optional prefix consisting of 1 or more digits, followed by a '.', followed by
(?<sfx>[0-9]+) # a mandatory suffix, consisting of 1 or more digits, followed by
(?<ext>[.]pdf) # a '.pdf' extension, followed by
$ # end-of-text
",
rxOptions
);

Related

Remove specific characters except last

I have a text string and I want to replace the dots with underscores except for the last character found in the string.
Example:
input = "video.coffee.example.mp4"
result = "video_coffe_example.mp4"
I have a code but this replaces everything including the last character
first option failed
static string replaceForUnderScore(string file)
{
return file = file.Replace(".", "_");
}
I implemented a second option that works for me but I find that it is very extensive and not very optimized
static string replaceForUnderScore(string file)
{
string result = "";
var splits = file.Split(".");
var extension = splits.LastOrDefault();
splits = splits.Take(splits.Count() - 1).ToArray();
foreach (var strItem in splits)
{
result = result + "_" + strItem;
}
result = result.Substring(1, result.Length-1);
string finalResult = result + "."+extension;
return finalResult;
}
Is there a better way to do it?
Since you work with files, I suggest using Path class: all
we want is to change file name only while keeping extension intact:
static string replaceForUnderScore(string file) =>
Path.GetFileNameWithoutExtension(file).Replace('.', '_') + Path.GetExtension(file);
You can replace all the dots with an underscore except for the last dot by asserting that there is still a dot present to the right when matching one.
string result = Regex.Replace(input, #"\.(?=[^.]*\.)", "_");
The result will be
video_coffee_example.mp4
Regex will help you to do this.
Add the namespace using System.Text.RegularExpressions;
And use this code:
var regex = new Regex(Regex.Escape("."));
var newText = regex.Replace("video.coffee.example.mp4", "_", 2);
Here we specified the maximum number of times to replace the .
The output would be the following:
video_coffee_example.mp4
Additionally, you can update the code to replace any number of dots excluding the last one.
var replaceChar = '.';
var regex = new Regex(Regex.Escape(replaceChar.ToString()));
var replaceWith = "_";
// The text to process
var text = "video.coffee.example.mp4";
// Count how many chars to replace excluding extension
var replaceCount = text.Count(s => s == replaceChar) - 1;
var newText = regex.Replace(text, replaceWith, replaceCount);
Off the top of my head but this might work.
return $"{file.Replace(".mp4","").Replace(".","_")}.mp4";
The simplest (and probably fastest) way is just to iterate over the string:
static string replaceForUnderScore(string file)
{
StringBuilder sb = new StringBuilder( file.Length ) ;
int lastDot = -1 ;
for ( int i = 0 ; i < file.Length ; ++i )
{
char c = file[i] ;
// if we found a '.', replace it with '_' and save its position
if ( c == '.' )
{
c = '_' ;
lastDot = i ;
}
sb.Append( c ) ;
}
// if we changed any '.' to '_', convert the last such replacement back to '.'
if ( lastDot >= 0 )
{
sb.Replace ( '.' , '_' , lastDot, 1 );
}
return sb.ToString();
}
Another approach would be to use System.IO.Path. It's certainly the most succinct:
static string replaceForUnderScore( string file )
{
string ext = Path.GetExtension( file ) ;
string name = Path
.GetFileNameWithoutExtension( file )
.Replace( '.' , '_' )
;
return Path.ChangeExtension( name , ext ) ;
}

Remove text between quotes

I have a program, in which you can input a string. But I want text between quotes " " to be removed.
Example:
in: Today is a very "nice" and hot day.
out: Today is a very "" and hot day.
Console.WriteLine("Enter text: ");
text = Console.ReadLine();
int letter;
string s = null;
string s2 = null;
for (s = 0; s < text.Length; letter++)
{
if (text[letter] != '"')
{
s = s + text[letter];
}
else if (text[letter] == '"')
{
s2 = s2 + letter;
letter++;
(text[letter] != '"')
{
s2 = s2 + letter;
letter++;
}
}
}
I don't know how to write the string without text between quotes to the console.
I am not allowed to use a complex method like regex.
This should do the trick. It checks every character in the string for quotes.
If it finds quotes then sets a quotesOpened flag as true, so it will ignore any subsequent character.
When it encounters another quotes, it sets the flag to false, so it will resume copying the characters.
Console.WriteLine("Enter text: ");
text = Console.ReadLine();
int letterIndex;
string s2 = "";
bool quotesOpened = false;
for (letterIndex= 0; letterIndex< text.Length; letterIndex++)
{
if (text[letterIndex] == '"')
{
quotesOpened = !quotesOpened;
s2 = s2 + text[letterIndex];
}
else
{
if (!quotesOpened)
s2 = s2 + text[letterIndex];
}
}
Hope this helps!
A take without regular expressions, which I like better, but okay:
string input = "abc\"def\"ghi";
string output = input;
int firstQuoteIndex = input.IndexOf("\"");
if (firstQuoteIndex >= 0)
{
int secondQuoteIndex = input.IndexOf("\"", firstQuoteIndex + 1);
if (secondQuoteIndex >= 0)
{
output = input.Substring(0, firstQuoteIndex + 1) + input.Substring(secondQuoteIndex);
}
}
Console.WriteLine(output);
What it does:
It searches for the first occurrence of "
Then it searches for the second occurrence of "
Then it takes the first part, including the first " and the second part, including the second "
You could improve this yourself by searching until the end of the string and replace all occurrences. You have to remember the new 'first index' you have to search on.
string text = #" Today is a very ""nice"" and hot day. Second sentense with ""text"" test";
Regex r = new Regex("\"([^\"]*)\"");
var a = r.Replace(text,string.Empty);
Please try this.
First we need to split string and then remove odd items:
private static String Remove(String s)
{
var rs = s.Split(new[] { '"' }).ToList();
return String.Join("\"\"", rs.Where(_ => rs.IndexOf(_) % 2 == 0));
}
static void Main(string[] args)
{
var test = Remove("hello\"world\"\"yeah\" test \"fhfh\"");
return;
}
This would be a possible solution:
String cmd = "This is a \"Test\".";
// This is a "".
String newCmd = cmd.Split('\"')[0] + "\"\"" + cmd.Split('\"')[2];
Console.WriteLine(newCmd);
Console.Read();
You simply split the text at " and then add both parts together and add the old ". Not a very nice solution, but it works anyway.
€dit:
cmd[0] = "This is a "
cmd[1] = "Test"
cmd[2] = "."
You can do it like this:
Console.WriteLine("Enter text: ");
var text = Console.ReadLine();
var skipping = false;
var result = string.Empty;
foreach (var c in text)
{
if (!skipping || c == '"') result += c;
if (c == '"') skipping = !skipping;
}
Console.WriteLine(result);
Console.ReadLine();
The result string is created by adding characters from the original string as long we are not between quotes (using the skipping variable).
Take all indexes of quotes remove the text between quotes using substring.
static void Main(string[] args)
{
string text = #" Today is a very ""nice"" and hot day. Second sentense with ""text"" test";
var foundIndexes = new List<int>();
foundIndexes.Add(0);
for (int i = 0; i < text.Length; i++)
{
if (text[i] == '"')
foundIndexes.Add(i);
}
string result = "";
for(int i =0; i<foundIndexes.Count; i+=2)
{
int length = 0;
if(i == foundIndexes.Count - 1)
{
length = text.Length - foundIndexes[i];
}
else
{
length = foundIndexes[i + 1] - foundIndexes[i]+1;
}
result += text.Substring(foundIndexes[i], length);
}
Console.WriteLine(result);
Console.ReadKey();
}
Output: Today is a very "" and hot day. Second sentense with "" test";
Here dotNetFiddle

Split numeric and Non-Numeric in a String

If I have a string value like this "1234-", then I need to split till the non-numeric character that is - and add numeric value 1 after the non-numeric char. later I have to update the value to "1234-1". Then the program will check with the last updated value 1234-1 then it will increment by 1 every time and store it for future use. If no non-numeric in a string then the program will increment by 1 with the numeric string.
Below are some examples of String and Output Value
Ex Str1 Output
2014- 2014-1
2014-1 2014-2
AAA AAA1
ABC-ABC ABC-ABC1
12345 12346
1234AA 1234AA1
I have used the below code before.
Code
var SiteFile = (from site in db.SiteFiles where site.Code == "ACQPONUM" select site.Line2).FirstOrDefault(); // Get Input string to generate AUTO number.
int Count = (from Porders in db.Porders where Porders.No.StartsWith(SiteFile) select Porders.No).ToList().Count; // Get the count of matching values in db.
var PONo = (from Porders in db.Porders where Porders.No.StartsWith(SiteFile) select Porders.No).ToList(); // Get list of Matching existing values.
if (Count != 0)
{
if (PONo != null)
{
int Val = (from PONos in PONo let value = Regex.Match(PONos, #"\d+").Value select Convert.ToInt32(value == string.Empty ? "0" : Regex.Match(PONos, #"\d+").Value) + 1).Concat(new[] { 0 }).Max(); // Fiind the maximum value in the matched list nd Increment value by if same type exists in the db.
porder.No = SiteFile + Val.ToString();
}
}
else
{
porder.No = SiteFile + "1";
}
Any help to this will be appreciated.
Maybe something like this:
string s = "123419";
string res = null;
char ch = s[s.Length - 1];
if(char.IsDigit(ch)) // handle numbers
{
res = s.Substring(0,s.Length - 1);
string suffix = null;
// special case
if(ch == '9'){
suffix = "10";
}
else
{
suffix = (++ch).ToString();
}
res += suffix;
}
else
{
res = string.Format("{0}1", s);
}
Try this code:
private string Incrementvalue(string str)
{
string retVal;
if (str.Contains(DELIMITER))
{
string[] parts = str.Split(new char[] { DELIMITER }, 2);
string origSuffix = parts[1];
string newSuffix;
int intSuffix;
if (int.TryParse(origSuffix, out intSuffix))
//Delimiter exists and suffix is already a number: Increment!
newSuffix = (intSuffix + 1).ToString();
else
//Delimiter exists and suffix is NTO number: Add a "1" suffix.
newSuffix = origSuffix + 1;
retVal = parts[0] + DELIMITER + newSuffix;
}
else
{
int temp;
if (int.TryParse(str, out temp))
{
//Delimiter does not exists and the input is a number: Increment last digit!
string newSuffix = (int.Parse(str[str.Length - 1].ToString()) + 1).ToString();
retVal = str.Substring(0, str.Length - 1) + newSuffix;
retVal = str.Substring(0, str.Length - 1) + newSuffix;
}
else
{
//Delimiter does not exists and the input is NOT a number: Add a "1" suffix.
retVal = str + "1";
}
}
return retVal;
}
The code could be written in a much more compact manner, but think this will be more readable and it will work...

How to split string with date in c#

i have string with date , i want to split it with date and string
For example :
I have this type of strings data
9/23/2013/marking abandoned based on notes below/DB
12/8/2012/I think the thid is string/SG
and i want to make it like as
9/23/2013 marking abandoned based on notes below/DB
12/8/2013 I think the thid is string/SG
so, i don't know how to split these strings and store in different columns of table.
pls help me.
string[] vals = { "9/23/2013/marking abandoned based on notes below/DB",
"12/8/2012/I think the thid is string/SG" };
var regex = #"(\d{1,2}/\d{1,2}/\d{4})/(.*)";
var matches = vals.Select(val => Regex.Match(vals, regex));
foreach (var match in matches)
{
Console.WriteLine ("{0} {1}", match.Groups[1], match.Groups[2]);
}
prints:
9/23/2013 marking abandoned based on notes below/DB
12/8/2012 I think the thid is string/SG
(\d{1,2}/\d{1,2}/\d{4})/(.*) breaks down to
(\d{1,2}/\d{1,2}/\d{4}):
\d{1,2} - matches any one or two digit number
/ - matches to one / symbol
\d{4} - matches to four digit number
(...) - denotes first group
(.*) - matches everything else and creates second group
Another way to do it with LINQ:
var inputs = new[]{
"9/23/2013/marking abandoned based on notes below/DB",
"12/8/2012/I think the thid is string/SG"
};
foreach (var item in inputs)
{
int counter = 0;
var r = item.Split('/')
.Aggregate("", (a, b) =>
a + ((counter++ == 3) ? "\t" : ((counter == 1) ? "" : "/")) + b);
Console.WriteLine(r);
}
Or you may use the IndexOf and Substring methods:
foreach (var item in inputs)
{
var lastPos =
item.IndexOf('/',
1 + item.IndexOf('/',
1 + item.IndexOf('/')));
if (lastPos != -1)
{
var r = String.Join("\t",
item.Substring(0, lastPos),
item.Substring(lastPos + 1, item.Length - lastPos - 1));
Console.WriteLine(r);
}
}
Perhaps with pure string methods, the third slash separates the date and the text:
string line = "9/23/2013/marking abandoned based on notes below/DB";
int slashIndex = line.IndexOf('/');
if(slashIndex >= 0)
{
int slashCount = 1;
while(slashCount < 3 && slashIndex >= 0)
{
slashIndex = line.IndexOf('/', slashIndex + 1);
if(slashIndex >= 0) slashCount++;
}
if(slashCount == 3)
{
Console.WriteLine("Date:{0} Text: {1}"
, line.Substring(0, slashIndex)
, line.Substring(slashIndex +1));
}
}
For what it's worth, here is a extension method to "break" a string in half on nth occurence of astring:
public static class StringExtensions
{
public static string[] BreakOnNthIndexOf(this string input, string value, int breakOn, StringComparison comparison)
{
if (breakOn <= 0)
throw new ArgumentException("breakOn must be greater than 0", "breakOn");
if (value == null) value = " "; // fallback on white-space
int slashIndex = input.IndexOf(value, comparison);
if (slashIndex >= 0)
{
int slashCount = 1;
while (slashCount < breakOn && slashIndex >= 0)
{
slashIndex = input.IndexOf(value, slashIndex + value.Length, comparison);
if (slashIndex >= 0) slashCount++;
}
if (slashCount == breakOn)
{
return new[] {
input.Substring(0, slashIndex),
input.Substring(slashIndex + value.Length)
};
}
}
return new[]{ input };
}
}
Use it in this way:
string line1 = "9/23/2013/marking abandoned based on notes below/DB";
string line2 = "12/8/2012/I think the thid is string/SG";
string[] res1 = line1.BreakOnNthIndexOf("/", 3, StringComparison.OrdinalIgnoreCase);
string[] res2 = line2.BreakOnNthIndexOf("/", 3, StringComparison.OrdinalIgnoreCase);

split text in a text file

How can I split a text file where I have various length of sentences inside and I want to read the text file when I click to button1 on my form and take, extract words from that text file that are between start and the end of ' character and which contains # symbol or # symbol inside the start and end of ' character and I want to know which line is it in and output the words into the text file.
Example, lets say I have a text like
abc'123'#def'456''#ghi'
abc'123'#def'#456''#ghi'123456'
output:
1st sentence #ghi
2nd sentence #456 #ghi
PS: #def is not in start and end of ' character so not in the output
I tied with split function but couldn't make it and turned into mass: ( How can I make this. I will be pleased if someone who knows helps.
Thanks.
here ur input string is s & the string contains # or # at first index is str
int start = s.indexOf("'");
int end = s.indexOf("'", start + 1);
string str = s.SubString(start, end);
if(str.ToCharArray()[0] == "#" || str.ToCharArray()[0] == "#")
// proceed
As far as this example is concerned here is a sample code that works
string sen1="abc'123'#def'456''#ghi'";
string sen2 = "abc'123'#def'#456''#ghi'123456'";
string[] NewSen = Regex.Split(sen1, "''");
string YourFirstOP=NewSen[1].ToString(); //gets #ghi
NewSen = Regex.Split(sen2, "''");
string[] A1 = Regex.Split(NewSen[0], "'");
string[] A2 = Regex.Split(NewSen[1], "'");
string YourSecondOP= A1[A1.Length - 1] + "" + A2[A2.Length - 3].ToString();// gets #456 #ghi
But thats just this example
Hope this helps
Try this,
string testString = #"abc'123'#def'456''#ghi'abc'123'#def'#456''#ghi'123456'";
List<string> output = new List<string>();
int startIndex = 0;
int endIndex = 0;
while (startIndex >= 0 && endIndex >= 0)
{
startIndex = testString.IndexOf("'", endIndex + 1);
endIndex = testString.IndexOf("'", startIndex + 1);
if (startIndex >= 0 && endIndex >= 0)
{
string str = testString.Substring(startIndex + 1, (endIndex - startIndex) - 1);
int indexOfSpecialChar = str.IndexOf("#");
if (indexOfSpecialChar < 0)
{
indexOfSpecialChar = str.IndexOf("#");
}
if (indexOfSpecialChar >= 0)
{
output.Add(str.Substring(indexOfSpecialChar));
}
}
}
string [] Mass = s.Split('\'');
if (Mass.Length > 1)
for (int i = 1; i < (Mass.Length - 1); i += 2)
{
if (Mass[i].Contains("#") || Mass[i].Contains("#"))
// proceed
}

Categories

Resources