PDA

View Full Version : مشکل در خواندن خط به خط فایل متنی



samiasoft
شنبه 30 اردیبهشت 1396, 22:41 عصر
سلام دوستان

فرض کنید یک فایل متنی به شکل زیر داریم »


aaaaaaaaaaaaaaa
name:sami
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:sami2
bbbbbbbbbbbbbbb



من میخواستم به روش خواندن خط به خط نام ها را جدا کنم و هرکدوم در یک تکست باکس قرار بدم.برای همین اومدم این دستور رو نوشتم :
TReader = new System.IO.StreamReader(openFileDialog1.FileName);

strLine = TReader.ReadLine();
while (!(strLine == null))
{

if (strLine.StartsWith("name"))
{
listBox3.Items.Add(strLine);
}
strLine = TReader.ReadLine();
}
TReader.Close();
TReader = null;


میبنید من در این حالت هرکاری کردم نتونستم اون خطی که میخونه رو جداکنم و مجبور شدم بریزمشون تو لیست باکس...ایا نمیشه در این حالت هرخط را جداگانه در تکست باکس مجزا فرستاد؟

ramtinak
یک شنبه 31 اردیبهشت 1396, 00:25 صبح
سلام،
یعنی مثلا فقط میخوای sami و sami2 رو برات از متن بگیره؟ یعنی بعد از name: هر چی بود؟
// zamani ke dari ba stream kar mikoni behtare ke az using // estefade koni ta khodkar bar az khondane akharin khat az blockesh
// khodkar compiler oun ro dispose kone
using (var TReader = new System.IO.StreamReader(dialog.FileName))
{
var strLine = TReader.ReadLine();


while (strLine != null)
{
var searchtag = "name:";
if (strLine.StartsWith(searchtag))
{
var newStr = strLine.Substring(searchtag.IndexOf(searchtag) + searchtag.Length);
// newStr har chizi k bad name: dar line gharar dare hast
listBox1.Items.Add(newStr);
}
strLine = TReader.ReadLine();
}
}

موفق باشید.

samiasoft
یک شنبه 31 اردیبهشت 1396, 02:05 صبح
تشکر از پاسخگویی شما
اما دستوراتی که نوشتید پاسخ من نبود متاسفانه !

ببینید مشکل من در تجزیه سطرهای خوانده شده است.

در مثالی که زدم به چه صورت
sami را در تکست باکس1 و sami 2 را در تکست باکس2 قرار بدم؟!!!

درواقع newStr یا strLine که هربار سطر رو میخونه چگونه بگم سطر دومی که خونده رو ازش بگیرم یا سطر اولی که خونده را؟


البته میشد بعد از ریختن در لیست باکس سطرهارو از اون استخراج کرد اما خود این روش خواندن خط به خط راهی برای انجام این کار نداره؟

امیدوارم منظورمو خوب توضیح داده باشم.


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

aaaaaaaaaaaaaaa
name:sami
name:ali
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:sasan
name:sara
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:mohsen
bbbbbbbbbbbbbbb

با چه دستوری میتوانم سطرهایی که میخواستم رو بدین صورت نمایش بدم :

http://s8.picofile.com/file/8295466084/2017_05_20_152928.png

ramtinak
دوشنبه 01 خرداد 1396, 10:02 صبح
سلام
اول اینکه متنت هیچ الگوی خاصی نداره که آدم بخواد براش تجزیه سازی کنه.
تنها چیزی که هست اینه که یکی در میون اسم ها به لیست ها اضافه میشه، یعنی اسم اول به لیست 1 و اسم دو به لیست 2، اسم سه به لیست 1 و ....
پس نیاز هست که این ها رو با استفاده از لیستِ دیگه ای درست کنیم،
من اومدم یه لیست از نوع رشته درست کردم و جای اینکه بیام مستقیما به لیست باکس ها اضافه کنم، اومدم به لیستی که دستی ساختم اضافه کردم که بعدا بیام یکی در میون اونها رو به لیست باکس ها اضافه کنم.

فضای نامی مورد نیاز:
using System.Collections.Generic;


// zamani ke dari ba stream kar mikoni behtare ke az using
// estefade koni ta khodkar bad az khondane akharin khat az blockesh
// khodkar compiler oun ro dispose kone
using (var TReader = new System.IO.StreamReader(dialog.FileName))
{
var strLine = TReader.ReadLine();
// jaye inke biaim mostaghim be listboxhamon item ezafe konim,
// ye list az noe string misazim ke badan yeki dar mion item ha ro
// be list box hamon add konim
// name space e zir niaze:
// using System.Collections.Generic;
List<string> list = new List<string>();
// hatman listet bayad biron az halghat bashe!!!

while (strLine != null)
{
var searchtag = "name:";
if (strLine.StartsWith(searchtag))
{
var newStr = strLine.Substring(searchtag.IndexOf(searchtag) + searchtag.Length);
// newStr har chizi k bad name: dar line gharar dare hast
list.Add(newStr);
}
strLine = TReader.ReadLine();
}


// boolean misazim ke age true bod be listbox2 add kone
// age true bod be listbox1
// inam hatman bayad biron az halghe bashe
bool flag = false;
// ba estefade az halghe foreach tuye halghe micharkhim!
foreach (string item in list)
{
// age flag false bod be listbox1 item ro add mikonim
if (flag == false)
listBox1.Items.Add(item);
else
// age nabod be listbox2
listBox2.Items.Add(item);


// keyword e ! ham miad harchizi ke flag bode ro bar ax mikone
// yani alan code zir mige, age flag false bod oun ro true kon,
// ya barax age true bod oun ro false kon.
flag = !flag;
}
}

راستی یادم رفت بگم، این روش هم یه مشکل داره اونم اینه که طبق چیزی که نوشتی
در هر بار دوتا اسم وجود داره به جز مورد آخرت، الان اگه بعد از bbbbbb آخرین خط بیای دو تا نام دیگه اضافه کنی، کلا به هم میخوره و اسمی که باید توی لیست 1 بره میره توی لیست 2 و برعکس!



موفق باشید.

ramtinak
دوشنبه 01 خرداد 1396, 10:51 صبح
یه روش هست کمی سخت تره اما مشکل بالایی رو نداره، من میگم برای کسایی که دوست دارن بدونن.
ساخت کلاس + استفاده از Split.
یک کلاس نیاز داریم که دو پراپرتی از نوع رشته داشته باشه، رشته اول متن اول و رشته دوم باید متن بعدی رو در خودش نگه داره.
میایم کل متن رو با استفاده از تابع ReadToEndـه متغیر StreamReader میگیریم و درون یک رشته میریزیم.
بعد یک لیست از نوع رشته ایجاد میکنیم و متن رو Split می کنیم به لاین های متفاوت.
سپس لیستی از کلاسی که ساختیم ایجاد میکنیم.
با استفاده از حلقه for میایم توی لیست اسپلیت شده میچرخیم و آیتم ها رو میگیریم.
از کلاسی که ساختیم یک متغیر ایجاد می کنیم.
اگه آیتم بعدی یا همون خط بعدی با name: شروع شده بود، یعنی آیتم بعدی هم باید اسمش رو بگیریم.
آیتم اول رو میریزیم توی متغیر اول کلاسمون و آیتم دوم اگه وجود داشت میریزیم توی متغیر دوم کلاس اگه هم نبود که هیچ، پس اگه نبود متغیر دوم کلاسمون null هست.


برای اضافه کردن به لیست از Linq استفاده میکنیم، با استفاده از تابع Any توی لیست جستجو می کنیم و میگیم اگه توی لیستمون، آیتم بعدی(دوم) برابر با آیتم اول چیزی هست که میخوایم اضافه کنیم نبود، به لیست اضافه ش کن، اگه بود که هیچ کاری انجام نده، دلیل این کار این هست که آیتم دوم رو جای آیتم اول اضافه نکنیم.
بیرون از حلقه for حلقه دیگری از نوع foreach میسازیم که درون لیست بچرخه، توی این میایم میگیم آیتم اول رو به لیست اول اضافه میکنیم و یه شرط میزاریم که اگه آیتم دوم null یا خالی نبود به لیست باکس دوم اضافه شه.
این کد ها:
فضاهای مورد نیاز:
using System.Diagnostics;
using System.Linq;


ساخت کلاس مورد نیاز:
public class TestCS
{
public string CurrentText { get; set; }
public string NextText { get; set; }
}


باقی کدها:
using (var TReader = new System.IO.StreamReader(dialog.FileName))
{
string content = TReader.ReadToEnd();


List<string> splittedList = new List<string>(content.Split(new string[]
{
Environment.NewLine
}, StringSplitOptions.RemoveEmptyEntries));


List<TestCS> list = new List<TestCS>();


for (int i = 0; i < splittedList.Count; i++)
{
string item = splittedList[i];
var searchtag = "name:";
if (item.StartsWith(searchtag))
{
var newStr = item.Substring(item.IndexOf(searchtag) + searchtag.Length);
// newStr har chizi k bad name: dar line gharar dare hast
TestCS t = new TestCS();
Debug.WriteLine(i + " " + newStr);


t.CurrentText = newStr;


if (splittedList.Count > (i + 1))
{
string nextItem = splittedList[i + 1];
if (nextItem.StartsWith(searchtag))
t.NextText = nextItem.Substring(nextItem.IndexOf(searchtag) + searchtag.Length);
}
if (list.Any(s => s.NextText == newStr) == false)
list.Add(t);


}
}
foreach (TestCS item in list)
{
if (string.IsNullOrEmpty(item.NextText) == false)
listBox2.Items.Add(item.NextText);
listBox1.Items.Add(item.CurrentText);
}
}





موفق باشید.

samiasoft
چهارشنبه 03 خرداد 1396, 22:48 عصر
یه روش هست کمی سخت تره اما مشکل بالایی رو نداره، من میگم برای کسایی که دوست دارن بدونن.
ساخت کلاس + استفاده از Split.
یک کلاس نیاز داریم که دو پراپرتی از نوع رشته داشته باشه، رشته اول متن اول و رشته دوم باید متن بعدی رو در خودش نگه داره.
میایم کل متن رو با استفاده از تابع ReadToEndـه متغیر StreamReader میگیریم و درون یک رشته میریزیم.
بعد یک لیست از نوع رشته ایجاد میکنیم و متن رو Split می کنیم به لاین های متفاوت.
سپس لیستی از کلاسی که ساختیم ایجاد میکنیم.
با استفاده از حلقه for میایم توی لیست اسپلیت شده میچرخیم و آیتم ها رو میگیریم.
از کلاسی که ساختیم یک متغیر ایجاد می کنیم.
اگه آیتم بعدی یا همون خط بعدی با name: شروع شده بود، یعنی آیتم بعدی هم باید اسمش رو بگیریم.
آیتم اول رو میریزیم توی متغیر اول کلاسمون و آیتم دوم اگه وجود داشت میریزیم توی متغیر دوم کلاس اگه هم نبود که هیچ، پس اگه نبود متغیر دوم کلاسمون null هست.


برای اضافه کردن به لیست از Linq استفاده میکنیم، با استفاده از تابع Any توی لیست جستجو می کنیم و میگیم اگه توی لیستمون، آیتم بعدی(دوم) برابر با آیتم اول چیزی هست که میخوایم اضافه کنیم نبود، به لیست اضافه ش کن، اگه بود که هیچ کاری انجام نده، دلیل این کار این هست که آیتم دوم رو جای آیتم اول اضافه نکنیم.
بیرون از حلقه for حلقه دیگری از نوع foreach میسازیم که درون لیست بچرخه، توی این میایم میگیم آیتم اول رو به لیست اول اضافه میکنیم و یه شرط میزاریم که اگه آیتم دوم null یا خالی نبود به لیست باکس دوم اضافه شه.


موفق باشید.

تشکر از شما بابت راهنمایی...خیلی در این زمینه به کمک کردید.

فقط یه قسمتیشو من نتونستم حل کنم این که :

اگر کلمه name: رو نتونست پیداکنه علامت - رو در سطر مربوطه لحاظ کنه...این رو در کجای دستورات بالا بنویسیم؟

ramtinak
جمعه 05 خرداد 1396, 08:27 صبح
منظورتون رو دقیقا نفهمیدم
میخواهید چیکار کنید؟ اگه با تصویر نشون بدید بهتره.
------------------------------
اگه منظورتون اینه که اگه اسم دوم وجود نداشت بجاش - بذاره یعنی به این شکل:

145316
لیست من این شکلی هست:

aaaaaaaaaaaaaaa
name:sami
name:ali
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:sasan
name:sara
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:mohsen
bbbbbbbbbbbbbbb
aaaaaaaaaaaaaaa
name:iman
name:paria
bbbbbbbbbbbbbbb

کافیه در حلقه دوم یعنی foreach (TestCS item برای دستور if یک else بگذارید:

foreach (TestCS item in list) {
if (string.IsNullOrEmpty(item.NextText) == false)
listBox2.Items.Add(item.NextText);
else
listBox2.Items.Add(" - ");
listBox1.Items.Add(item.CurrentText);
}

همین!
موفق باشید.

samiasoft
جمعه 05 خرداد 1396, 12:07 عصر
تشکر از شما

منظورم این بود ممکن است حتی اسم اول هم وجود نداشته باشه و علامت - را میخواستم منظور کنم.

ینی نه اسم اول و نه اسم دوم باشه که برابر سطرش در لیست باکس 1 و 2 بجاشون علامت - رو قرار بدیم

برای این کار چه دستوری رو قرار بدیم؟

ژیار رحیمی
شنبه 06 خرداد 1396, 04:52 صبح
سلام در این جور شرایط بهتره به جای فایل متنی از فرمت های json و یا xml استفاده کنی.