PDA

View Full Version : ایجاد تغییر در فایل متنی



ParsiPax
جمعه 23 فروردین 1392, 14:14 عصر
سلام...

اینبار تاپیک با رعایت قوانین هست (درخواست کد نیست...)

دوستان با توجه به الگوریتمی که برای خودم نوشته بودم:

1. شروع

2. فایل متنی C:\\Users\\ParsiPax\\Desktop\\1.txt را بخوان.

3. خطی که با کلمه ی "0x2" شروع می شود را پیدا کن.

4. در این خط عدد 1 رو:


0x2 int 1 16777216 cap_rd=alwayspass cap_wr=WriteDeviceData


بیاب و اونو تبدیل کن به 19:


0x2 int 19 16777216 cap_rd=alwayspass cap_wr=WriteDeviceData


5. فایل را در C:\\Users\\ParsiPax\\Desktop\\2.txt ذخیره کن.

6. پایان.

با جستجو های بسیار در نت و پیدا کردن لینکی در سایت مایکروسافت تونستم یک کد رو به شکل مورد نیازم تغییر بدم:



List<string> proName = new List<string>();
string path = @"C:\\Users\\ParsiPax\\Desktop\\1.txt";
string pathxx = @"C:\\Users\\ParsiPax\\Desktop\\2.txt";
System.IO.StreamReader rdr = new System.IO.StreamReader(path);
System.IO.StreamWriter wrt = new System.IO.StreamWriter(pathxx);

string line;
while ((line = rdr.ReadLine()) != null)
{
if (line.Contains("0x2"))
{
string[] val = line.Substring(line.IndexOf(' ') + 5).Split(' ');
proName.Add(val[0].ToString());
}

}
foreach (string nam in proName)
{

Console.WriteLine(nam.ToString());
line = line.Replace(nam, "19");
wrt.WriteLine(line);
}



کد بالا عدد 1 رو با موفقیت در متغیر nam قرار میده اما نمیتونه اونو با 19 جایگزین کنه و ارور زیر رو میده:


.Object reference not set to an instance of an object


میخوام بدونم اشکال کار از کجاست و چه کنم :ناراحت:

ممنون.

ParsiPax
جمعه 23 فروردین 1392, 18:25 عصر
فایل متنی مربوطه ضمیمه شد...

danialafshari
جمعه 23 فروردین 1392, 20:47 عصر
سلام
بفرمائید:

ParsiPax
شنبه 24 فروردین 1392, 14:30 عصر
سلام
بفرمائید: سلام

از مثالی که گذاشتید ممنونم، اما،

1. بنده نمیخوام کاربر عدد رو برای Find و Replace وارد کنه، الگوریتم رو دوباره ببینید...

2. ارور The given path's format is not supported رو میده...

3. اگه ممکنه کد خودم رو تصحیح کنید...

ممنون.

mehrdad1991h
شنبه 24 فروردین 1392, 17:57 عصر
سلام

از مثالی که گذاشتید ممنونم، اما،

1. بنده نمیخوام کاربر عدد رو برای Find و Replace وارد کنه، الگوریتم رو دوباره ببینید...

2. ارور The given path's format is not supported رو میده...

3. اگه ممکنه کد خودم رو تصحیح کنید...

ممنون.

این مثالی که برات گذاشتن خیلی بهتره
با این حال بیا از این یکی هم میتونی استفاده کنی
همش را توضیح دادم که بفهمی چی کار کردیم


//مسیر اولیه را به یک رشته نصبت میدیم که راحت تر ازش استفاده کنیم
string source = @"C:\Users\ParsiPax\Desktop\1.txt";

// چک میکنیم ببینیم اصلا همچین فایلی وجود داره یا نه
if (System.IO.File.Exists(source))
{
//لود کردن فایل از ادرسی که روی سیستم هست
System.IO.StreamReader rdr = new System.IO.StreamReader(source);

//تموم خطوط را یه دفعه ای میخونیم و به کاربر تویه یه تکست باکس نشون میدیم
textBox1.Text = rdr.ReadToEnd();

//(میتونی هم بریزی تو یه رشته ای چیزی )
//string Read_all_line = rdr.ReadToEnd();


//خطوط را به یک ارایه نصبت میدهیم

string[] All_Lines = textBox1.Lines;

//اگر همه خطوط را ریخته باشی در یک رشته اینجوری باید جدا کنیشون
//string[] All_Lines = Read_all_line.Split(new string[] { "\r\n" }, StringSplitOptions.None);

// متن جدید را میخوایم به یه رشته نصبت دهیم پس تعریفش میکنیم
string Result = "";

//در یک حلقه تک تک خطوط را میخوانیم
for (int i = 0; i < All_Lines.Count(); i++)
{
// چک میکنیم که ایا با حرف مد نظر شروع شده یا نه
if (All_Lines[i].StartsWith("0x2"))
{
// اگر شروع شده بود عدد را جایگزین میکنیم
All_Lines[i] = All_Lines[i].Replace("1", "19");
}

//در هر صورت اگر تغییر کرده باشه خط یا نکرده باشه فرقی نداره
// درون تکست باکس برش میگردونیم
Result += All_Lines[i] + "\r\n";//"\r\n" برای اینه که بریم خط بعدی چون متن جدید خط بعدی ما محسوب میشه
}

//ردر را میبندیمش
rdr.Close();

// در ادرس جدید ذخیره میکنیم
System.IO.File.WriteAllText("C:\\Users\\ParsiPax\\Desktop\\2.txt", Result);
//اینجا ممکنه با خطا مواجه بشی
//چون ممکنه فلدر ی با این نام ها که توی مسیری که نوشتی وجود نداشته باشه و ارور بهت بده
//برای جلوگیری از مواجه شدن با خطا میتونی 2 تا کار کنی
//چک کنی تک تک فدر ها وجود دارن یا نه دونه دونه بری جلو مثل کد بالا که چک کردیم فایل هست یا نه
// یا اینکه از کد زیر استفاده کنی و فایل را کنار خود همین پروژه ات ذخیره اش کنی
//System.IO.File.WriteAllText(Environment.CurrentDir ectory + @"\1.txt", Result);



//اینجام یه متنی چیزی به کاربر نشون میدیم اگر دلمون خواست
// که بدون فایلش ذخیره شده
MessageBox.Show("متن مورد نظر در فایل ذخیره شد", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else//اگر فایل وجود نداشت
{
MessageBox.Show("فایل اصلی موجود نیست", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}



اینم سورس برنامه ( دانلود کن ببین (http://barnamenevis.org/attachment.php?attachmentid=102762&d=1365861405))

102762

موفق باشید

ParsiPax
شنبه 24 فروردین 1392, 18:11 عصر
ممنون از راهنمایی عالیتون :)

فقط یه مشکل کوچیک هست... اینکه ممکنه توی فایل متنی بجای عدد 1 مثلا عدد 99 یا 2 یا هر عدد دیگه ای باشه...

پس باید برای بدست آوردن اون عدد، باید از 5 کاراکتر بعد از کلمه ی int شروع به دریافت و تا حرف اسپیس ادامه پیدا کنه تا عدد مورد نظر هرچه که بود بدست بیاد...

برای همین از کد پست اول استفاده کردم، ممنون میشم راهنمایی کنید...

linux
شنبه 24 فروردین 1392, 18:19 عصر
ممنون از راهنمایی عالیتون :)

فقط یه مشکل کوچیک هست... اینکه ممکنه توی فایل متنی بجای عدد 1 مثلا عدد 99 یا 2 یا هر عدد دیگه ای باشه...

پس باید برای بدست آوردن اون عدد، باید از 5 کاراکتر بعد از کلمه ی int شروع به دریافت و تا حرف اسپیس ادامه پیدا کنه تا عدد مورد نظر هرچه که بود بدست بیاد...

برای همین از کد پست اول استفاده کردم، ممنون میشم راهنمایی کنید...
چرا با regx ها کار نمی‌کنی؟

ParsiPax
شنبه 24 فروردین 1392, 18:29 عصر
چرا با regx ها کار نمی‌کنی؟

regx ها؟ اگر ممکنه لینک تاپیکی که در موردشون توضیح مختصری بده رو بدید...

ممنونم :)

ParsiPax
شنبه 24 فروردین 1392, 20:48 عصر
با تشکر از mehrdad1991h (http://barnamenevis.org/member.php?211255-mehrdad1991h) عزیز، مثال ایشون رو با کد خودم ترکیب و خلاصه سازی و تکمیل کرده و کد زیر رو ساختم:


string path;
List<string> proName = new List<string>();
path = @"C:\Users\ParsiPax\Desktop\1.txt";

using (System.IO.StreamReader rdr = new System.IO.StreamReader(path))
{
string line;
while ((line = rdr.ReadLine()) != null)
{
if (line.Contains("0x2 int"))
{
string[] val = line.Substring(line.IndexOf(' ') + 5).Split(' ');
proName.Add(val[0].ToString());
}
}
}
foreach (string nam in proName)
{

Console.WriteLine(nam.ToString());

if (System.IO.File.Exists(path))
{
System.IO.StreamReader rdr = new System.IO.StreamReader(path);

string Read_all_line = rdr.ReadToEnd();

string[] All_Lines = Read_all_line.Split(new string[] { "\r\n" }, StringSplitOptions.None);

string Result = "";

for (int i = 0; i < All_Lines.Count(); i++)
{
if (All_Lines[i].StartsWith("0x2"))
{
All_Lines[i] = All_Lines[i].Replace(nam, "19");
}

Result += All_Lines[i] + "\r\n";
}

rdr.Close();

System.IO.File.WriteAllText("C:\\Users\\ParsiPax\\Desktop\\2.txt", Result);
System.IO.File.Copy("C:\\Users\\ParsiPax\\Desktop\\2.txt", "C:\\Users\\ParsiPax\\Desktop\\1.txt", true);
System.IO.File.Delete("C:\\Users\\ParsiPax\\Desktop\\2.txt");
}
else
{
MessageBox.Show("File does not excist in selected directory", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

}

Console.ReadLine();


حالا سوالی که دارم اینه که میشه اونو خلاصه تر نوشت، یا همینو بکار ببرم؟ چون این کد قراره برای چندین فایل متنی، چندین بار تکرار بشه... (با مقدار های مختلفِ بجز 19)

منتظر جواب دوستان عزیز هستم :)

linux
شنبه 24 فروردین 1392, 23:11 عصر
regx ها؟ اگر ممکنه لینک تاپیکی که در موردشون توضیح مختصری بده رو بدید...

ممنونم :)
regular expression ها خیلی با مزه هستند! از حدود ۴۰ سال پیش هم سر و کله شون پیدا شد تو unix و دستورات grep ,awd,sed همشون ازش استفاده می‌کنند هر چند هر کدام ساختار خودشان را دارند در سی‌شارپ http://www.codeproject.com/Articles/93804/Using-Regular-Expressions-in-C-NET وجود دارند و دقیقا راست کار شماست.

ParsiPax
یک شنبه 25 فروردین 1392, 10:08 صبح
regular expression ها خیلی با مزه هستند! از حدود ۴۰ سال پیش هم سر و کله شون پیدا شد تو unix و دستورات grep ,awd,sed همشون ازش استفاده می‌کنند هر چند هر کدام ساختار خودشان را دارند در سی‌شارپ http://www.codeproject.com/Articles/93804/Using-Regular-Expressions-in-C-NET وجود دارند و دقیقا راست کار شماست.

ممنون بابت لینک :)

اما از اونا نمیشه برای ویرایش استفاده کرد، میشه؟

mehrdad1991h
یک شنبه 25 فروردین 1392, 15:14 عصر
ممنون بابت لینک :)

اما از اونا نمیشه برای ویرایش استفاده کرد، میشه؟

خوب با اون چیزی که میخوای را پیدا میکنی بعد ویرایش میکنی دیگه

بابا این کدی که تو نوشتی چیه اخه forech یه حلقه هست برای تکرار ، که گذاشتی اون بالا ! یعنی همینجوری تموم چیزایی که یرش هست را هی تکرار میکنه تا شرطش نقض بشه ، میدونی ؟
بیا این یکی را بگیر کارت را راه میندازه دیگه.
فقط کافی بود داخل if که من گذاشته بودم را اینجوری تغیرش میدادی
در کد زیر من همه جا نوشتم System.Text.RegularExpressions شما میتونی بالای برنامه همین فضای نام را اضافه کنی و هرجای دیگه نوشته شده System.Text.RegularExpressions پاکش کنی
کد زیر را اینجوری نوشتم که بفهمی چیکار میکنیم



// چک میکنیم که ایا با حرف مد نظر شروع شده یا نه
if (All_Lines[i].StartsWith("0x2"))
{


// الگوی چیزی که میخوای پیدا کنه را میزنیم
// d+ یعنی یک یا چند عدد
string Pattern = @"int \d+ ";

// اینجا میگیم اگر متناسب با الگو در متن چیزی پیدا کردی
if (System.Text.RegularExpressions.Regex.IsMatch(All_ Lines[i].ToString(), Pattern))
{

//m اینجا چیزی که پیدا میکنه را به دستش میاریم میریزیمش تو
System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(All_Lin es[i], @"int \d+ ");

// الان چیزی که پیدا کرده را با چیزی که میخوایم جایگزین میکنیم
//"int 1 " در این مثال چیزی که پیدا میکنه اینه
// بالا "" را گذاشتم که بدونی فاصله هم محسوب شده تو چیزی که پیدا کرده
//"int 19 " به همین خاطر الان با این باید جایگزینش کنیم
All_Lines[i] = All_Lines[i].Replace(m.ToString(), "int 19 ");
}
}



اینم سورس برنامه جدید ( دانلود (http://barnamenevis.org/attachment.php?attachmentid=102814&d=1365938051) )

102814

راستی در کد من اگر دقت کرده باشی سرچ نمیکنه ببینه "0x2" تو اون خط هست یا نه فقط اول خط را چک میکنه که با "0x2" شروع شده یا نه اگه میخوای تو کل خط چک کنه ببینه "0x2" در اون خط موجود هست یا نه اینجوری تغییر بده
این قسمت را
.StartsWith("0x2")
تغییرش بده به این
.Contains("0x2")

ParsiPax
یک شنبه 25 فروردین 1392, 17:46 عصر
آقا بینهایت ممنون بابت تصحیح کد پر اشکال بنده :)

همچنین ممنون از linux عزیز بابت آشنا کردن بنده با regex ها :)

دوستان لطف بسیار بزرگی در حقم کردید :)