PDA

View Full Version : سوال: نوشتن در خطی خاص از فایل



masanar
پنج شنبه 15 مرداد 1388, 11:08 صبح
سلام
جمیعا خدا قوت
کسی میدونه چطور میشه واسه نوشتن تو یه فایل txt به جای شروع از ابتدای فایل از یه خط خاص شروع کرد یا به ترتیب پیش نرفت مثلا اول توخط یک بعد تو خط دهم بنویسیم؟؟؟

Reza_Yarahmadi
پنج شنبه 15 مرداد 1388, 16:19 عصر
اگر اندازه همه سطرها برابره که کار راحته ولی اگر هر خط اندازه متفاوتی داره میتونی اول کل فایل رو بخونی و اندازه هر سطر و توی یه آرایه ذخیره کنی ، بعد از متد Seek از کلاس FileStream استفاده کنی. این متد اشاره گر فایل رو به جایی که میخوای ، انتقال میده و میتونی از اونجا به بعد بخونی.

masanar
پنج شنبه 15 مرداد 1388, 18:11 عصر
از اینکه به سوالم جواب دادید خیلی ممنون
اما ببینید هیچ فایلی برای خوندن وجود نداره! قراره یه فایل خالی ایجاد بشه و در یه سری از خطوط اون نوشته بشه.یعنی میشه بامتد seek این کار رو کرد؟خوب من چطور از متد seek بخوام که مثلا به خط دهم بره ؟ یعنی باید چی رو به عنوان پارامتر این متد قرار بدم که به خطوطی که من میخوام بره و فقط در اونها بنویسه ؟

tdkhakpur
پنج شنبه 15 مرداد 1388, 19:37 عصر
سلام
اولا فایل شما باید تعداد مورد نظر خط داشته باشه که بتوانید به اون خط دسترسی داشته باشید.
ثانیا باید طول خط را بدانید یا اینکه توسط کلاسی مانند TString فایل را لود کرده باشید که این کلاس به شما کمک کند.
فی الواقع اگر میخواهید خودتان با فایل کار کنید میتوانید خط مورد نظر را در طول خط ضرب کرده و مقدار حاصل را در تابع seek استفاده کنید تا ابتدای خط مورد نظر گیرتان بیاد.

Reza_Yarahmadi
پنج شنبه 15 مرداد 1388, 19:37 عصر
اگر فایل خالی باشه ، یعنی خطی هم وجود نداره که شما بخواید به nامین خط اون برید و مقداری درش درج کنید!
برای این مثال اول باید 10 خط ایجاد کنید بعد اشاره گر فایل رو ُSeek کنید به خط 10 و اونجا داده مورد نظرتون رو درج کنید.
متد Seek برحسب اندازه (تعداد بایت) اشاره گر رو جابجا میکنه.
یک نکته: اگر فایل حاوی 10 خط اطلاعات باشه و بخواید بین خط 4 و 5 یک خط جدید اضافه کنید قضیه کلا فرق میکنه! اول باید 4 خط اول فایل رو بخونید و توی یه فایل کمکی ذخیره کنید ، داده مورد نظرتون رو به فایل کمکی اضافه کنید بعدش هم بقیه فایل اصلی رو بخونید و به فایل کمکی اضافه کنید. در نهایت فایل کمکی رو جایگزین فایل اصلی کنید (چی شد!!)
دقیقا بگید چه چیزی مد نظرتونه تا بهتر بشه کمک کرد.

masanar
جمعه 16 مرداد 1388, 13:11 عصر
از راهنماییتون ممنون :لبخندساده:



فکرکنم یه چیزایی دست گیرم شد اما هنوز یکم گیجم . خوب از اول براتون میگم قضیه چیه :

من یه آرایه خیلی بزرگ دارم که کل کلمات فایل های تی ایکس تی هاردم رو در خودش داره هر کدوم از عناصر علاوه بر کلمه مورد نظر یه آرایه از فایل هایی که اون کلمه درشون هست داره که هر کدوم از عناصر این آرایه هم شامل مسیر فایل و یه آرایه ی دیگه است که شامل مکانهایی از هر کدوم از اون فایلهاست که کلمه مورد نظر درش هست . فکر کنم حالا شما هم مثل من گیج شدین !! خلاصه اینکه من یه آرایه با یه ساختار پیچیده دارم که مشخص میکنه کلمات موجود در فایلهای هاردم هر کدوم در چه فایلهایی و ودر هر فایل در چه نقاطی وجود دارن .

من باید تو این آرایه جستجو انجام بدم اما قبلش باید اون رو به نحوی در هارد ذخیره کنم که بشه یه جستجوی درست درش انجام بدم . مشکل هم همینجاست !!!
استادمون روش هشینگ رو پیشنهاد داد اما من فکر نمیکنم با این آرایه ای که ما داریم پیاده سازی هشینگ کار ساده ای باشه ؟؟!!
حالا من میخوام یه طور دیگه این آرایه رو ذخیره کنم میخوام یه فایل تی ایکس تی ایجاد کنم و از اول شروع کنم و فقط خود کلمات آرایه رو در هر خط بنویسم البته بعد از هر کلمه و یه فضای خالی یه عدد وجود داره که خطی از فایل باید باشه که مسیر فایلهایی که اون کلمه درشون هست به ترتیب و هر کدوم در یه خط نوشته بشه و دوباره در کنار هر مسیری یه عدد که خطی از فایل رو مشخص کنه که نقاط وجود اون کلمه در هر کدوم از اون مسیرهاست به ترتیب و هر کدوم در یه خط نوشته شده . یعنی اول فایل کل کلماتم بعد کل مسیرها و بعد کل نقاط موجود در فایلها اما چون به ترتیب پیش نمیرم مثلا وقی یه کلمه رو مینویسم باید آدرس یه خط در کنارش قرار بدم و به اون خط برم و دوباره همین کار رو واسه اون مسیر انجام بدم نیاز دارم که به خطی از فایل برم که در جلوی اون کلمه مشخص شده !! حالا مشکل من همینه !! که چطور به یه خط مشخص برم ؟؟ با توجه به اینکه اندازه خطوطم متفاوته و در بین هردو خط ممکنه خطوطی وجود داشته باشه که خالیه یا اینکه بعدا پر میشه ! و اینکه باید طول یه خط رو اونقدر بزرگ در نظر بگیرم که طولانی ترین عناصرم هم در یه خط جا بشه !!
شما گفتین اول باید به تعداد مورد نظر خط ایجا کنم مثلا این کار رو با یه حلقه و نوشتن متد writeline
انجام دادم بعد اگه مثلا خط 12 رو بخوام اگه 12 رو در یه طولی که بدونم برای خطوطم کم نمیاد ضرب کنم و اون رو به تابع
seek بدم به خط 12 میره؟؟
میدونم زیاد حرف زدم اگه شما روهم گیج کردم معذرت میخوام .
راستی نظرتون در مورد ایده من چیه ؟ شما راه دیگه ای پیشنهاد نمی کنید؟

Yasersadegh
جمعه 16 مرداد 1388, 13:33 عصر
سلام دوست عزيز
من با توجه به چيزي كه متوجه شدم نظرم رو خدمتتون عرض مي كنم!!
ببينيد به نظر من كاري كه مي خواهيد انجام بديد به فرض اگر هم يه طوري به سختي بتونيد عمليش كنيد اونوقت برايه عمل بعدي كه همون سرچ در اين فايل هست خيلي مشكل خواهيد داشت و سرعت عمليات كند ميشه يعني
--شما اول كل تكست هاي هارد رو ميگرديد تبديل به يه آرايه ي خفن مي كنيد...
--بعد اين آرايه رو به سختي تبديل به يه فايل تكست مي كنيد...
--بعدشم تازه مياييد تويه اين فايل تكست جستجو انجام ميديد كه جواب درخواست كاربر رو بديد!!!
درسته!!!؟
خوب اگه درسته به نظرتون خيلي راه طولاني و پيچيده اي نيست و عمليات خيلي كند نميشه!!!؟
به نظر من اگر شما در همون مرحله اول به جايه ذخيره تويه آرايه اطلاعاتتون رو تويه يه ديتابيس ذخيره كنيد كلي كارتون راحتتر و سريعتر ميشه!!!:متفکر:
چرا شما از ديتابيس استفاده نمي كنيد!!!؟:متعجب:

masanar
جمعه 16 مرداد 1388, 17:50 عصر
دوست خوبم از اینکه با دقت مطلب من رو خوندید و نظرتون رو گفتین خیلی ممنون
اتفاقا من هم قبلا به پیشنهاد شما فکر کردم اما به علت پیچیده بودن کارم یا ساختار جداول مناسب نخواهد بود و جستجو امکان پذیر نیست یا به تعداد حداقل کل کلماتم که بالغ بر 20000 تاست جدول در دیتا بیس خواهم داشت که عقلانی به نظر نمیاد علاوه بر این نباید زمان اتصال به بانک و جستجو در جداول که یه جستجوی ترتیبی هستش رو نادیده گرفت . حرف شمادر مورد پیچیدگی کار کاملا درسته اما وقتی فایل نهایی شکل گرفت و در هارد ذخیره شد حالا با توجه به ساختاری که من برای فایل در نظر گرفتم البته اگه بتونم پیاده سازیش کنم هر بار که جستجو انجام میشه فقط کافیه اون فایل txt باز بشه از ابتدا که کلمات هستن جستجو بشه وقتی کلمه مورد نظر پیدا شد با توجه به آدرس خطی که در جلوی اون کلمه است به یه خط دیگه فایل میره که تمام فایلهای مربوطه به ترتیب قرار دارن و برای هر فایل هم آدرس خطی از فایل نهایی در مقابل اونها وجود داره که میتونه با پرش در اونها نقاطی از هر فایل که کلمه در اونهاست رو پیدا کنه یعنی با چند بار پرش و خوندن از فایل میتونه اطلاعات مورد نظر رو پیدا کنه که فکر نمیکنم سرعت کار خیلی کند بشه!!
نمیدونم تونستم شما رو قانع کنم یانه ؟؟
شایدم نظر شما در مورداستفاده از دیتا بیس و ساختار جداول طور دیگه ای باشه
در هر صورت خوشحال میشم اگه بازم نظرتون رو بگید :لبخندساده:

Yasersadegh
جمعه 16 مرداد 1388, 17:59 عصر
اتفاقا من هم قبلا به پیشنهاد شما فکر کردم اما به علت پیچیده بودن کارم یا ساختار جداول مناسب نخواهد بود و جستجو امکان پذیر نیست یا به تعداد حداقل کل کلماتم که بالغ بر 20000 تاست جدول در دیتا بیس خواهم داشت که عقلانی به نظر نمیاد
خوب دوست عزيز من نمي دونم شما رو چه حسابي مي گيد كه 20000 تا جدول در ديتابيس مي خواهيد ولي فكر نمي كنم كه هر چه قدر هم كه ساختار كاريتون پيچيده باشه بيش از سه تا پنج جدول احتياج داشته باشه!!!


علاوه بر این نباید زمان اتصال به بانک و جستجو در جداول که یه جستجوی ترتیبی هستش رو نادیده گرفت .
جستجو در ديتابيس اصلا ترتيبي نيست!! شما مي تونيد با يه كوئري چندين مورد رو همزمان باهم بدست بياريد در يك زمان خيلي كوتاه!!!!
ضمن اينكه بعيد مي دونم اين روشي كه برايه پياده سازي فايل در نظر گرفتي عملي باشه!!!

شما يه لطفي كن و يه بار ديگه دقيقا بگو كه از فايلهاي تكست هاردت چي مي خواي ذخيره كني و بعد ازش مي خواي چي بدست بياري!!؟ تا بهت بگم كه دقيقا ساختار ديتابيست به چه شكلي ميشه!!! احتمال خيلي زياد، فكر نمي كنم بيش از 3 جدول نياز باشه!!!
موفق باشي:چشمک:

Yasersadegh
جمعه 16 مرداد 1388, 18:07 عصر
خوب دوست عزيز حساب كردم!!!
حالا مي تونم بهتون دقيق بگم كه شما برايه پياده سازي اين عمليات دقيقا به سه جدول نياز داريد كه خيلي راحت مي تونيد مقدار دهي انجام بديد و به راحتي هم هر دوخاست رو به صورت يه كوئري از ديتابيس بگيريد!!!
اگر از SQLServer هم استفاده كنيد كه قدرت بيشتر و سرعت بيشتري در پردازش و جواب دهي نسبت به Access داره!!

شما يه جدول برايه فايلها و آدرسشون نياز داريد!!
يه جدول برايه هر يك از كلمات به همراه يه كد كلمه نياز داريد!!
يه جدول هم كه detail هست كه تعيين مي كنه كه هر كلمه در كدام فايل در كدام خط قرار داره!!!

اگه توضيحات بيشتر خواستيد بفرماييد!!!
موفق باشيد:چشمک:

masanar
شنبه 17 مرداد 1388, 09:50 صبح
اول بزارید از همه دوستانی که این تاپیک رو به دلیل عنوانش برای دیدن انتخاب کردن معذرت بخوام :خجالت: چون فکر کنم کمکم داریم از بحث اولیه فاصله میگیریم .
و اما دوست خوبم ممنون
راستش اصرار شما به استفاده از دیتابیس باعث شد تا منم جدی تر به این مسئله فکرکنم در مورد نظرتون حتما بیشتر فکر میکنم. احتمالا عملیه .اما خوشحال میشم اگه مشکلی داشتم بازم نظرتون رو ببینم.
راستی یه سوال:فرض کنیم جدول detail پنج فیلد داره که یکیش نوعش Auto هستش حالا سوال من اینه که با یه کوئری میشه همزمان هم مقدار اون 4 فیلد رو برای یه رکورد به جدول اضافه کرد و هم مقدار فیلد Auto اون رو استخراج کرد؟ چطور ؟
بازم ممنون :لبخندساده:

Yasersadegh
شنبه 17 مرداد 1388, 12:05 عصر
دوست عزيز فكر مي كنم تصميم درستي گرفتيد!!:چشمک:
شما مي تونيد با تحليل خوب و جامع از كاري كه مي خواهيد انجام بديد مي تونيد به راحتي با سه جدول اين كار رو انجام بديد!!
ضمنا هر كمكي كه بتونم انجام بدم بنده در خدمتم!!!
در مورد سوالتن هم تا اونجايي كه من مي دونم نه نميشه دو كار رو همزمان انجام داد!! بايد يه كوئري برايه Insert و يه كوئري برايه select بنويسيد!!!:متفکر:
ولي اگه برايه جدول ديتيلي كه بنده عرض كردم خدمتتون، اين سوال رو پرسيديد، بايد بگم كه اين جدول به فيلد Auto و يا فيلد كليدي نيازي نداره!!
درواقع اين جدول داراي فيلد كليد اصلي دو جدول ديگر و چند فيلد اضافه است كه به نيازتون از برنامه بستگي داره!!!:لبخندساده:
اگه بازم مشكلي بود من در خدمتم!!:چشمک:

Reza_Yarahmadi
شنبه 17 مرداد 1388, 15:26 عصر
نظر دوستمون درسته فقط یه مقدار زمانبر میشه چون بانک تمام رکوردها رو بررسی میکنه!
حالا منم نظر خودمو میگم دوستان اگه نظری در این مورد دارن خوشحال میشم اگه مطرح کنن.
اول آرایه ساخته شده رو بر اساس کلمات فایلهای txt مرتب کن
به جای 3تا جدول از 3تا فایل استفاده کن
فایل اول برای ذخیره سازی کلمات ، فایل دوم ذخیره آدرسها ، فایل سوم مکان وجود کلمه در فایل.
1 - بعد از مرتب سازی یک کلمه رو در فایل اول ذخیره کن بعد اندازه فایل دوم (از نظر بایت) رو جلوی اون کلمه ذخیره کن. بعدش سراغ فایل دوم برو و برای هر یک از آدرسها کارهای زیر رو انجام بده:
2 - بعد از ذخیره هر آدرس در فایل دوم ، اندازه فایل سوم رو بعد از آدرس ذخیره کن و سراغ فایل سوم برو :
3 - آدرس مکانهایی که کلمه مورد نظر (در مرحله 1) در فایلی که در مرحله 2 ثبت شد رو به فایل سوم اضافه کن.
4 - برای هر یک از آدرسها ، مرحله 2 و 3 رو انجام بده.
5 - وقتی که تمام آدرسها و مکانهای وجود کلمه در هر فایل رو ذخیره کردی به مرحله 1 برگرد.
6 - برای کلمات بعد هم همین مراحل رو انجام بده.
(چی شد! :گیج:)

برای بازیابی هم به روش زیر عمل کن:
- کلمه مورد نظرت رو توی فایل اول جستجو کن (چون کلمات مرتب هستند میتونی از روشی مثل جستجوی باینری استفاده کنی)
بعد از پیدا کردن کلمه ، عدد جلوی اون (A) و عدد جلوی کلمه بعد (B) رو بدست بیار (این اعداد ابتدا و انتهای آدرسها در فایل دوم هستند).
به آدرس A در فایل دوم برو و مقدار اون خط رو بخون.
عدد جلوی آدرس در فایل دوم (C) رو بدست بیار و به آدرس C از فایل سوم برو.
تمام اعداد این سطر حاوی مکانهایی هستن که کلمه در فایل وجود داره.
برای مابقی سطرهای فایل دوم تا رسیدن به B هم همین کارها رو انجام.
به این ترتیب فقط با چند پرش مستقیما به اطلاعات مورد نظرت میرسی.
شاید مراحل ذخیره سازی یه مقدار تودرتو و گنگ باشه ولی خوبی این روش اینه که بازیابی سرعت بالایی داره.

masanar
یک شنبه 18 مرداد 1388, 17:06 عصر
آقای یار احمدی نظرتون فوق العاده ست :تشویق: واقعا ممنون :لبخندساده:
راستش توی برنامه من سرعت حرف اول رو میزنه من با پایگاه داده پیاده سازی کردم اما همونطور که گفتین سرعتش خیلی پایین میاد .
و با نظر شما هم سعی کردم بنویسم. توی فایلها چیز درستی نوشته می شه اما تمام آدرس ها رو 0 مینویسه !! :ناراحت: حتما من در جای درستی متغیرهام رو تعریف نکردم . من برنامه رو مینویسم اگه میشه بگید اشکال کارم کجاست

StreamWriter sw = File.CreateText("C:/data files/words.txt");
StreamWriter spa = File.CreateText("C:/data files/paths.txt");
StreamWriter spo = File.CreateText("C:/data files/points.txt");
FileInfo fw =newFileInfo("C:/data files/words.txt");
FileInfo fpa =newFileInfo("C:/data files/paths.txt");
FileInfo fpo =newFileInfo("C:/data files/points.txt");
for (int i =1; i <= bst_array.GetUpperBound(0); i++)
{
if (bst_array[i].word != null)
{
sw.WriteLine(bst_array[i].word+","+fpa.Length.ToString());
for (int j = bst_array[i].wordh.GetLowerBound(0); j <= bst_array[i].wordh.GetUpperBound(0); j++)
{
spa.WriteLine(bst_array[i].wordh[j].file_path+","+fpo.Length.ToString());
for (int k = bst_array[i].wordh[j].wordf.GetLowerBound(0); k <= bst_array[i].wordh[j].wordf.GetUpperBound(0); k++)
{
spo.WriteLine(bst_array[i].wordh[j].wordf[k].line_word + "," + bst_array[i].wordh[j].wordf[k].pos_word + "," + bst_array[i].wordh[j].wordf[k].next_word + "," + bst_array[i].wordh[j].wordf[k].pre_word);
}
}
}
}

sw.Close();

spa.Close();

spo.Close();

bst_array آرایه ای هستش که کل اطلاعاتم درش هست و من قراره اونهارو ذخیره کنم.

Reza_Yarahmadi
یک شنبه 18 مرداد 1388, 19:57 عصر
دقیقا متوجه نشدم کدتون چطور کار میکنه (لطفا کدها رو توی تگ Code بنویسید)
ولی فکر کنم اگر تعریف شئ های FileInfo رو قبل از استفاده انجام بدید مشکل حل بشه.
یعنی تقریبا یه همچین چیزی:


StreamWriter sw = File.CreateText("C:/data files/words.txt");
StreamWriter spa = File.CreateText("C:/data files/paths.txt");
StreamWriter spo = File.CreateText("C:/data files/points.txt");
for (int i =1; i <= bst_array.GetUpperBound(0); i++)
{
if (bst_array[i].word != null)
{
FileInfo fpa =newFileInfo("C:/data files/paths.txt");
sw.WriteLine(bst_array[i].word+","+fpa.Length.ToString());
for (int j = bst_array[i].wordh.GetLowerBound(0); j <= bst_array[i].wordh.GetUpperBound(0); j++)
{
FileInfo fpo =newFileInfo("C:/data files/points.txt");
spa.WriteLine(bst_array[i].wordh[j].file_path+","+fpo.Length.ToString());
for (int k = bst_array[i].wordh[j].wordf.GetLowerBound(0); k <= bst_array[i].wordh[j].wordf.GetUpperBound(0); k++)
{
spo.WriteLine(bst_array[i].wordh[j].wordf[k].line_word + "," + bst_array[i].wordh[j].wordf[k].pos_word + "," + bst_array[i].wordh[j].wordf[k].next_word + "," + bst_array[i].wordh[j].wordf[k].pre_word);
}
}
}
}

در فایل سوم بهتره تمام آدسهایی که کلمه در فایل وجود داره رو در یک سطر بنویسید. اینطوری زمان خوندن کار خیلی راحتتره چون فقط یک خط رو میخونید.

masanar
یک شنبه 18 مرداد 1388, 21:11 عصر
قبلا امتحان کردم بازم مشکل حل نمیشه :ناراحت:
ضمنا به خاطر پیشنهادتون هم ممنون :لبخندساده:اینطوری خیلی بهتره.

Reza_Yarahmadi
یک شنبه 18 مرداد 1388, 21:39 عصر
اگه بتونید برنامه رو بذارید راحتتر میشه کمک.

masanar
دوشنبه 19 مرداد 1388, 14:28 عصر
خدا رو شکر اون مشکل حل شد. این طوری :


FileInfo fw = new FileInfo("C:/data files/words.txt");
StreamWriter sw = fw.AppendText();
for (int i =1; i <= bst_array.GetUpperBound(0); i++)
{
if (bst_array[i].word != null)
{
FileInfo fpa = new FileInfo("C:/data files/paths.txt");
StreamWriter spa = fpa.AppendText();
sw.WriteLine(bst_array[i].word+","+fpa.Length.ToString());
Console.WriteLine(bst_array[i].word + "," + fpa.Length.ToString());
for (int j = bst_array[i].wordh.GetLowerBound(0); j <= bst_array[i].wordh.GetUpperBound(0); j++)
{
FileInfo fpo = new FileInfo("C:/data files/points.txt");
StreamWriter spo = fpo.AppendText();
spa.WriteLine(bst_array[i].wordh[j].file_path+","+fpo.Length.ToString());
for (int k = bst_array[i].wordh[j].wordf.GetLowerBound(0); k <= bst_array[i].wordh[j].wordf.GetUpperBound(0); k++)
{
spo.Write(bst_array[i].wordh[j].wordf[k].line_word + "," + bst_array[i].wordh[j].wordf[k].pos_word + "," + bst_array[i].wordh[j].wordf[k].next_word + "," + bst_array[i].wordh[j].wordf[k].pre_word+";");
}
spo.WriteLine();
spo.Close();
}
spa.Close();
}
}
sw.Close();

حالا یه سوال دیگه:
تو مرحله بازیابی وقتی کلمه رو تو فایل اول پیدا کردم و عدد جلوی اون و کلمه بعد رو به عنوان آدرسهای شروع و پایان برای خوندن از فایل دوم به دست آوردم .چطور می تونم از آدرس شروع تا پایان رو خط به خط بخونم؟ اگه از حلقه استفاده کنم باید چند تا چند تا اندیسم رو اضافه کنم چون اندازه هر کدوم از خطوط تو فایل دوم که مشخص نیست ؟؟؟ :متفکر:

Reza_Yarahmadi
دوشنبه 19 مرداد 1388, 15:15 عصر
میشه بصورت زیر عمل کرد:

long StartPosition = 15;
long EndPosition = 37;
string LineText;
FileStream FS = new FileStream(@"C:/Temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamReader SR = new StreamReader(FS);
while (StartPosition < EndPosition)
{
FS.Seek(StartPosition, SeekOrigin.Begin);
LineText = SR.ReadLine();
StartPosition += LineText.Length + 2;
//Your Commands Continuance
}