הדרך המהירה ביותר לאתחל מערך מדיסק
-
מדובר באינדקס של תוכנת חיפוש
כלומר אני סורק קבצים ולכל קובץ אני בונה אובייקט שמכיל את כל המילים שיש בקובץ שזה בעצם מערך של מחרוזות ועוד כמה פרטים כמו שם הקובץ ותאריך כניסה לאינדקס וכדומה.
אח''כ אני שומר אותו בדיסק, כך קובץ אחר קובץ אני סורק ושומר את הסיכום שלו בדיסק ע''י הפקודה Write עבור כל איבר באוביקט הנ''ל, התוכנית כתובה ב VB של דוטנט.בבניית האינדקס המהירות די מספקת כיון שזה לא כל כך קריטי אם הבניה תהיה כמה שניות יותר או פחות, אבל העינין הוא שכאשר מתבצע החיפוש וצריך לקרוא את האינדקס מהדיסק אני חייב כדי לאתחל את האוביקט הנ''ל לקרא עם ReadString איבר אחר איבר וזה לוקח בין שלוש לארבע שניות בקובץ אינדקס בגודל של שמונים מגה. כאשר כמובן לקרוא בבת אחת את כל הקובץ לזיכרון לוקח עשירית השניה. ואפילו אחרי שהקובץ נמצא בזיכרון לפרק את הביטים שלו למחרוזות ולאתחל את האובייקט לוקח כמעט אותו הזמן.
פורסם במקור בפורום CODE613 ב02/07/2013 18:00 (+03:00)
-
לפי מה שאתה אומר הבעייה היא לא בIO.
אלא בהפיכת המאפיינים מטיפוסים שונים לשרשרת בתים ולהיפך.זאת אומרת הנקודה היא הדקדוקי עניות של קריאת הדיסק וההמרה לאובייקטים.
תנסה לתת את העבודה השחורה למחלקות קיימות, תבדוק אם זה משפר את המהירות.
לדוגמא, DataTable של דוט נט.
תוסיף לפרוייקט דטהסט (קליק ימני על הפרוייקט Add New Item...>DataSet)
תבנה בתוך חלון העיצוב DataTable חדש. תוסיף עמודות ותגדיר את שמם והטיפוס שלהם (בחלון המאפיינים).אח"כ אתה משתמש בDataTable ככה בערך:
Dim dt As New MyDataSet.TavlaDataTable 'קראה מהדיסק dt.ReadXml("data.xml") 'כתיבה לדיסק dt.WriteXml("data.xml") '**************** 'הוספת שורה לטבלה Dim NewRow = dt.NewTavlaRow() 'גישה לתא כמאפיין NewRow.ColumnNane = 5265 'גישה לתא באינדקס נומרי NewRow(0) = "" 'גישה לתא באינדקס שם העמודה NewRow("תאריך") = #1/1/2013# 'הוספת השורה החדשה שיצרנו dt.AddTavlaRow(NewRow) 'לולאה על כל השורות For Each r In dt Console.WriteLine(r.ColumnName) Next
בדוגמא הראיתי כמה גישות לתא בטבלה, המועדפת זו הראשונה ע"י מאפיין.
פורסם במקור בפורום CODE613 ב02/07/2013 18:36 (+03:00)
-
עוד אפשרות מובנית בדוט נט זה הסריאליזציה המובנית.
הנה קטע קוד שעתקתי מהאינטרנט להמחשה:
Imports System.IO Imports System.Runtime.Serialization.Formatters Module Module1 Sub Main() Dim rnd As New Random Dim intArr(5, 5) As Int32 For i As Int32 = 0 To 5 For j As Int32 = 0 To 5 intArr(i, j) = rnd.Next(10, 100) Next Next Dim f As New Binary.BinaryFormatter() Dim ms As New MemoryStream() f.Serialize(ms, intArr) Dim byArr As Byte() = ms.ToArray() Dim str_b64 As String = Convert.ToBase64String(byArr) Dim ms2 As New MemoryStream(Convert.FromBase64String(str_b64)) Dim intArr2(,) As Int32 = f.Deserialize(ms2) End Sub End Module
פורסם במקור בפורום CODE613 ב02/07/2013 18:50 (+03:00)
-
את הסירילזציה הזו אני כבר ניסית והיא יוצרת קובץ פי כמה יותר גדול וגם בפי כמה יותר זמן ממה שאני עשיתי כנ''ל.
וגם את protobuf-net ניסיתי ואף שהוא הרבה יותר מהיר מה BinaryFormatter עדיין מה שעשיתי כנ''ל הרבה יותר מהיר גם ממנו.
וזה מה שעשיתי בתחילה: וזה הרבה יותר איטי וגם אתה חייב לקרוא את כל הקובץ בבת אחת ללא יכולת לדלג לאוביקט שנמצא במקום אחר בקובץPublic Sub Save(Obj As Object, Filename As String) Dim File As FileStream = New FileStream(Filename, FileMode.Create) Serializer.Serialize(File, Obj) File.Close() End Sub Public Sub Load(Of T)(aFilename As String, ByRef Obj As T) Dim File As FileStream = New FileStream(aFilename, FileMode.Open) Obj = Serializer.Deserialize(Of T)(File) File.Close() End Sub
פורסם במקור בפורום CODE613 ב02/07/2013 20:21 (+03:00)
-
נכון אני גם בחיים לא משתמש בה בגלל שתי הסיבות שהזכרת: גודל ומהירות.
רק שחשבתי שעדיין זה אולי יהיה מהר יותר במקרה שלך מאשר המרת Bytes לטיפוסים אחד אחד.
הבעיה השנייה שאמרת שא"א לקרוא אובייקט ספציפי, מה שנקרא קריאה רנדומלית, זה לא אמור להפריע לך כי אתה מעלה הכל ברגע לזיכרון.עדיין אני בטוח שהDataTable כן ייתן תוצאות טובות מבחינת מהירות, תעדכן.
מבחינת גודל בדיסק הוא גם לוקח הרבה יותר מהגודל שאתה מצפה כי הוא כותב הכל בXML.
אם תרצה לחסוך גם את זה אולי מסד נתונים קומפקטי יעזור (Access, SqlIite, SqlCompact). במקרה כזה גם הקריאה/כתיבה וגם נפח הדיסק עוברים לשליטת מסד הנתונים (בדרך כלל הוא מטפל בזה מצויין).פורסם במקור בפורום CODE613 ב02/07/2013 20:39 (+03:00)
-
השאלה היא איך עושים את זה באוצר החכמה ובפרוייקט השות שהחיפוש שלהם הוא מהיר מאוד והאינדקסים שלהם גדולים מאוד ויש גם תוכנה שנקראת dtSearch שמחפשת במהירות עצומה ממש והפלא שאם תראה את האינדקס שלהם הכל מלא אפסים ???
פורסם במקור בפורום CODE613 ב02/07/2013 20:42 (+03:00)
-
השאלה היא איך עושים את זה באוצר החכמה ובפרוייקט השות שהחיפוש שלהם הוא מהיר מאוד והאינדקסים שלהם גדולים מאוד ויש גם תוכנה שנקראת dtSearch שמחפשת במהירות עצומה ממש והפלא שאם תראה את האינדקס שלהם הכל מלא אפסים ???
הם לא מחפשים על הזיכרון החי. (אם הם היו, זה היה הרבה יותר מהר. כמו השלמה אוטומטית. רק שבכאלה כמויות הם לא יכולים וזה גם הרבה הרבה זמן טעינה מיותרת).
הם קוראים מקובץ בעל אפשרות גישה רנדומלית/מסד נתונים, והחיפוש הוא בעצם על אינדקסים על הדיסק.
תוכל לנסות לעשות כך גם. הכי פשוט ליישם את זה במסד נתונים כשמקדישים טבלה לערכים, עם עמודה מאונדקסת.פורסם במקור בפורום CODE613 ב03/07/2013 11:31 (+03:00)
-
אבל זה בדיוק מה שעשיתי עד כעת!
וכמו שהסברתי לעיל שיש קובץ אינדקס שבו 200 אלף ביטים ראשונים שייכים לאוביקט סיכום של קובץ א' ואח''כ 150 אלף ביטים שייכים לאובייקט סיכום של קובץ ב' וכן על זה הדרך מאות ואלפי אובייקטים של סיכומי קבצים, וכשאני רוצה לחפש מילים בקובץ א' אני ניגש לתחילת המערך וקורא עד 200 אלף וכשאני צריך לחפש בקובץ ב' אני קורא מביט 200001 עד 350000 וכך מאתחל את האובייקט. וכן על זה הדרך.
ואם רוב הזמן הולך לא על קריאת הביטים מהדיסק אלא בהמרה של ביטים למחרוזות איך הם עושים את ההמרה מהר?פורסם במקור בפורום CODE613 ב03/07/2013 11:39 (+03:00)
-
אני חייב לציין שבהתחלה לא הבנתי שאתחול המערכים זה חלק מתהליך חיפוש.
אם הייתי יודע הייתי ישר אומר לך שזה מיותר.
במקום לקרוא ולחפש, חפש ישירות על הדיסק.אבל זה בדיוק מה שעשיתי עד כעת!
וכמו שהסברתי לעיל שיש קובץ אינדקס שבו 200 אלף ביטים ראשונים שייכים לאוביקט סיכום של קובץ א' ואח''כ 150 אלף ביטים שייכים לאובייקט סיכום של קובץ ב' וכן על זה הדרך מאות ואלפי אובייקטים של סיכומי קבצים, וכשאני רוצה לחפש מילים בקובץ א' אני ניגש לתחילת המערך וקורא עד 200 אלף וכשאני צריך לחפש בקובץ ב' אני קורא מביט 200001 עד 350000 וכך מאתחל את האובייקט. וכן על זה הדרך.
ואם רוב הזמן הולך לא על קריאת הביטים מהדיסק אלא בהמרה של ביטים למחרוזות איך הם עושים את ההמרה מהר?זה לא נקרא עדיין לגמרי קריאה רנדומלית.
צריך:
א. חיפוש מידע ספציפי מאוד, למשוך 200,000 זה המון. החיפוש הוא בטח על הרבה הרבה פחות. זה מה שאתה צריך לסרוק ולא נתוני כל הקובץ. אתה אמור לעבור בלולאה על כל בתי הקובץ ולבדוק התאמה לבלוק החיפוש.
ב. ההמרה צריכה להיות לפני הקריאה, מהמאפיינים לבתים, ואז חיפוש הבתים. ואז ההמרה היא רק פעם אחת לקריאת כל הקבצים.
ג. מהר פי כמה אם מקטעי הקובץ יהיו באורכים קבועים. כלומר כל N בתים מתחיל מילה, והשאר בבתים ריקים עד תחילת הבלוק הבא.
ככה אתה בודק בלוקים ולא בית בית. אגב זה ההגדרה של קובץ לקריאה רנדומלית.
ד. הכי טוב לכל זה, מסד נתונים. זה האופציה המודרנית לכל הבלגנים הללו. אם אתה רוצה אדריך אותך איך ליצור כזה.פורסם במקור בפורום CODE613 ב03/07/2013 12:04 (+03:00)
-
אני אבהיר את הדברים יותר:
א. נאמר שיש לי חמישה קבצים ונאמר שכל קובץ מכיל חומש מהתורה.
ב. עבור כל קובץ אני בונה אינדקס שמכיל את כל המילים שיש בקובץ. כל מילה מופיעה באינדקס פעם אחת עם המידע באילו מיקומים היא מופיעה באותו קובץ. מספר המיקומים הוא בעצם מספר הפעמים שאותה מילה קיימת בקובץ. את כל חמשת האינדקסים אני מאחסן בקובץ אחד רצוף ויש לי מידע איפה מתחיל כל אינדקס בתוך הקובץ הגדול.
ג. המשתמש מחפש כמה מילים עם מרחק מקסימלי בינהם, השאילתא יכולה להראות כך:
שלום {30} ברכה {11} הצלחה {22} שמחהד. כעת אני רוצה לחפש בכל אחד מחמשת האינדקסים הנ''ל האם יש בו צירוף של המילים הנ''ל עם מרחקים מקסימלים הנ''ל לצורך זה אני עושה את הדברים הבאים עבור כל אחד מחמשת האינדקסים.
ה. אני קורא מהאינדקס כל פעם כמה ביטים ומאתחל מערך שמכיל כנ''ל רשימת מילים והמיקומים שלהם, לאחר שיש לי מערך אני עובר עליו פעם אחת עבור כל מילה [לא על כולו ממש אלא על אחד חלקי 22 ממנו כי הוא ממויין לפי א''ב] ואז בוחן אם כל המילים שמצאתי מספיק קרובות אחת לשניה. ואז אני עובר לאינדקס הבא ומאתחל מערך חדש וחוזר חלילה.
זהו.כמובן שיש גם שאילתות עם כוכביות כמו:
שלום {30} ברה {11} הצלה {22} שמח
אם אני לא אמיר את כל הקובץ לטקסט איך יהיה אפשר לחפש?כעת מה כאן מיותר, לא נכון, וכדומה. ואיך נכנס לכאן המסד נתונים אם בכלל.
פורסם במקור בפורום CODE613 ב03/07/2013 19:06 (+03:00)
-
מה ממש לא נכון לדעתי, ההמרה של הבתים לאובייקטים, עוד לפני שווידאת שהם הם הרלוונטיים לך.
מה מיותר זה כבר מסובך, כי באמת אני חולק על הגישה האלגוריתמית לעניין.
אני חוזר בי מגישת מסד הנתונים, כי זה באמת לא הנקודה כאן.לדעתי צריך להיות:
[u:2hxx37a7]א. מילון[/u:2hxx37a7]
קובץ אחד שהוא מילון של כל המילים, והוא אמור להיות כולו בזיכרון מתחילת חיי היישום עד סופו. זה הכי פחות חשוב האופן בו הוא נכתב לדיסק ונטען ממנו.
כל מילה מופיעה פעם אחת, ומיקומה ביחס לתחילת המילון (לדוגמא המילה ה27) היא הזיהוי שלה.
[u:2hxx37a7]ב. אינדקס דחוס (+ כל ערך באורך קבוע)[/u:2hxx37a7]
האינדקס בעצם זה עותק של קובץ המקור אבל במקום לכתוב "פעם היה איש" לדוגמה, לכתוב (ע"פ המילון) שלושה קודי Integer שכל אחד לוקח ארבעה בתים תמיד.
אז יש לנו קובץ בינארי שאנו יודעים שהוא מורכב מ4 בתים * מספר המילים בקובץ.
[u:2hxx37a7]ג. חיפוש תוך כדי הקריאה[/u:2hxx37a7]
כשמחפשים לדוגמה את המילים: שלום {30} ברה {11} הצלה {22} שמח,
אז דבר ראשון נשיג מהמילון את קודי הזיהוי שלהם. לא בצורת מספר, אלא מספר מומר למערך בתים בגודל 4 (עדיף כבר במילון בזיכרון, אבל אם לא עכשיו).
דבר שני נעבור בלולאה של Stream על קובץ האינדקס שמורכב כאמור מסטים של ארבע ארבע בתים.
אז במהלך הלולאה שעוברת על בתי הקובץ (של האינדקס), לבדוק התאמה בין הקטע הנקרא כעת לבין אחד מאבעת הקודים אותם אנו מחפשים.
**[size=85:2hxx37a7]אפשר לעשות את זה תוך כדי (שהקריאה לא תחכה לבדיקה, והבדיקה לא תחכה לקריאה) אבל זה כבר מורכב יותר. אם תאחז בזה אשמח להראות לך איך.[/size:2hxx37a7]**אם נמצאה התאמה פותחים מונה שיבדוק את המרחק בין ההתאמה הזו לזו שאחריה, במידה וזה התאמה לא ראושנה נבדוק את המרחק ונחליט אם יש בהתאמה הוקדמת רלוונטיות לאור המרחק.כדי להבהיר את כוונתי אראה כאן קוד דוגמה:
בקשר לשאילתה שמרשה תווים מיוחדים כמו כוכבית זה מאוד קל ליישם זאת גם, אבל זה שלב נוסף.
פורסם במקור בפורום CODE613 ב04/07/2013 11:57 (+03:00)
-
א. לגבי המילון אני מבין שצריך לעשות מילון נפרד עבור כל קובץ כלומר כל קובץ יקבל מילון וגם קובץ אינדקס.
ב. לגבי האינדקס יוצא שאתה עושה את הספירה כמה פעמים כל מילה מופיעה תוך כדי חיפוש וזה לוקח זמן, אולי עדיף שכל מילה תופיע באינדקס כמספר כמו שאמרת, אבל רק פעם אחת ולצידה יופיעו מספרים שמציינים את מיקומי המילה בקובץ למשל תופיע מילה 'שלום' אבל לא כשלום אלא כמספר נאמר 20 כיון שזה המזהה של המילה 'שלום' במילון ואחר המספר 20 יופיע רצף של מספרים למשל 40 500 780 שזה אומר שהמילה 'שלום' מופיעה בקובץ המקורי כמילה ה 40 מתחילת הקובץ וכמילה ה500 מתחילת הקובץ וכו'.
עוד דבר שאתה מרויח בשיטה כזה, כאשר אתה רוצה לדעת את כל המיקומים של מילה מסויימת אתה מחפש אותה במילון ואם אתה מוצא אותה במילה ה20 מתחילת המילון אתה מיד נגש לאובייטק ה20 בקובץ האינדקס ושם יהיה לך את כל המיקומים שלו.
ובמחשבה שניה למה לא לאחד בין המילון לאינדקס? אחר כל מילה במילון יופיעו כל המופעים של אותה מילה בקובץ המקור.
וכדי לגשת ולעבור מהר בין מילה למילה במילון אפשר לעשות קובץ של 'תוכן עינינים' של המילון בצורה כזו:
התוכן עינינים יכיל מספרים, כל מספר יציין את המיקום שממנו מתחילה מילה במילון.
למשל המילה הראשונה מתחילה ב 0 כמובן, כי זה תחילת הקובץ אחר המילה מופיעים כל המיקומים שלה, המיקומים לוקחים למשל 200 ביטים מתחילת הקובץ, ואז מגיעה המילה השניה ואחריה כל המיקומים שלה וכן הלאה, אז בקובץ תוכן העינינים יהיה כתוב 0 200 350 וכדומה. וכשנרצה לגשת מילה אחר מילה נעביר את המצביע של קורא הקובץ למיקום הרצוי אחד אחר השני. נעביר ל 0 נקרא מילה אחת אם אין התאמה נעבור ל 200 נקרא מילה אחת אם יש התאמה נמשיך לקורא את כל מיקומי המילה ואז נעבור ל350 ונקרא עוד מילה ונבדוק התאמה, וכן הלאה.פורסם במקור בפורום CODE613 ב04/07/2013 12:38 (+03:00)
-
אני לא הבנתי אותך.
אתה דובק בשיטתך, סבורני שלא הבנת אותי.
זה חבל מאוד לכתוב מיקומים אחרי ערך כי אז אתה מסתבך אם הקריאה המהירה.
מלבד זאת מיקום לוקח מקום בדיוק כמו הערך, אז מה הטעם לכתוב גם מילה וגם מיקומה במקום פשוט לכתוב לפי הסדר?אני לא הדבקתי את הקוד קודם, אדביק אותו כאן
Sub SerachInIndex(WordsCodes() As Byte, fileIndex As String) Using Stream As New IO.FileStream(fileIndex, IO.FileMode.Open, IO.FileAccess.Read) Dim bytes(4095) As Byte Dim numBytesToRead As Integer = Stream.Length Dim numBytesRead As Integer = 0 While numBytesRead < numBytesToRead numBytesRead = Stream.Read(bytes, 0, 4096) For i As Integer = 0 To 1023 For Each WordCheck In WordsCodes If bytes.Skip(i).Take(4).SequenceEqual(WordsCodes) Then 'החזרת המיקום והמילה שנמצאה End If Next Next End While End Using End Sub
פורסם במקור בפורום CODE613 ב04/07/2013 14:18 (+03:00)
-
@דוד ל.ט.
זה חבל מאוד לכתוב מיקומים אחרי ערך כי אז אתה מסתבך אם הקריאה המהירה.
בשביל לקרוא מהר יש את התוכן עינינים שהסברתי לעיל, אני מקווה שהסברתי מספיק ברור. ע''י התוכן עינינים אתה עובר ממילה למילה אף שהם לא רצופות במהירות, ורק כאשר יש התאמה אתה מיד קורא גם את הביטים שאחר המילה ומקבל את כל המיקומים שלה ולא צריך להמשיך ולקרוא עד סוף הקובץ כדי למצוא את כל המיקומים של אותה מילה.
@דוד ל.ט.
מלבד זאת מיקום לוקח מקום בדיוק כמו הערך, אז מה הטעם לכתוב גם מילה וגם מיקומה במקום פשוט לכתוב לפי הסדר?
מה שאני מרויח הוא כנ''ל שלא צריך לקרוא עד סוף הקובץ, נציג את התהליך כך:
נאמר שאני מחפש את המילה 'שלום' תחילה אני אקרא את כל התוכן עינינים ואז מיד אני אדע איפה מתחילה כל מילה אתחיל לקרוא מילה אחר מילה אם המילה שקראתי היא 'שלום' מיד אני לוקח את כל המיקומים ויוצא מהקריאה.אפשר לעשות את זה עוד יותר מהר אם אשמור מידע על סדר הא''ב של תוכן העינינים, למשל אני יכול לציין לעצמי ש10 המספרים הראשונים בתוכן העינינים שייכים לאות א' ו20 הבאים הן מילים שמתחילות בב' וכו' וכך כאשר אני מחפש 'שלום' אני מיד אגש למספרים הרלוונטים בתוכן עינינים ועם המספרים האלו בלבד אלך ואקרא מהאינדקס את המילים שמתחילות בש'.
לדעתי זה יהיה ממש מהיר לא ?
פורסם במקור בפורום CODE613 ב04/07/2013 14:44 (+03:00)
-
לא כ"כ ירדנו זה לסוף דעתו של זה כפי הנראה.
(בקשר לקריאה, עדיין עדיף לקרוא קובץ רצוף רצוף בלי דילוגים, זה המצב. ממילא גם לשיטתך, צור שני קבצים. זכור גם שהקריאה עצמה לא היוותה בעיה מבחינת המהירות).
אדרבא תנסה מה שנראה לך, בכל עת תוכל לבדוק גם את דרכי ע"י קריאה בעיון במה שכתבתי.
אם בסוף העלית דרך טובה מבחינת התכלס,
אל תשכח לספר לנו אודותיה!פורסם במקור בפורום CODE613 ב04/07/2013 14:53 (+03:00)
-
אפשר לעשות את זה עוד יותר מהר אם אשמור מידע על סדר הא''ב של תוכן העינינים, למשל אני יכול לציין לעצמי ש10 המספרים הראשונים בתוכן העינינים שייכים לאות א' ו20 הבאים הן מילים שמתחילות בב' וכו' וכך כאשר אני מחפש 'שלום' אני מיד אגש למספרים הרלוונטים בתוכן עינינים ועם המספרים האלו בלבד אלך ואקרא מהאינדקס את המילים שמתחילות בש'.
רעיון מצויין. יש לי על היישום כמה הערות, בכל אופן זו בדיוק הדרך שבה עובדת הפונקציה BinarySearch שבמחלקת Array וכל יתר האוספים,
כך שלא תצטרך ליישם בעצמך את החיפוש, הפונקציה הזו מבצעת הכי מהר שייתכן.
שים לב שהיא עובדת כפי שצריך רק אם קודם לכן מיינת את המערך בסדר עולה.פורסם במקור בפורום CODE613 ב04/07/2013 17:30 (+03:00)
-
@דוד ל.ט.
יש לי על היישום כמה הערות
אשמח לשמוע ולהחכים.
@דוד ל.ט.
בכל אופן זו בדיוק הדרך שבה עובדת הפונקציה BinarySearch שבמחלקת Array וכל יתר האוספים,
כך שלא תצטרך ליישם בעצמך את החיפוש, הפונקציה הזו מבצעת הכי מהר שייתכן.שים לב שאין אני רוצה לאתחל מערך עם כל המילים אלא לעבור על כל המילים ישירות על הדיסק כעצתך לעיל וממילא אני מוכרח לכתוב בעצמי פונקציה לחיפוש בינארי זה. יש עוד שיטה לחיפוש בינארי כאן:
http://vlib.eitan.ac.il/ds1/block_find.htmפורסם במקור בפורום CODE613 ב04/07/2013 20:37 (+03:00)
-
@דוד ל.ט.
(בקשר לקריאה, עדיין עדיף לקרוא קובץ רצוף רצוף בלי דילוגים, זה המצב. ממילא גם לשיטתך, צור שני קבצים. זכור גם שהקריאה עצמה לא היוותה בעיה מבחינת המהירות).
באמת בדקתי וקריאה רצופה מהירה פי מאה מקריאה עם העברת מצביע כל פעם!
Dim MAX As Integer = 2000000 Dim SW As New Stopwatch Dim ARR(MAX) As Integer Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 'בניית הקובץ SW.Reset() SW.Start() Dim BW As New BinaryWriter(File.Open("C:\SS.TXT", FileMode.Create), Encoding.UTF8) For I = 2 To MAX + 2 BW.Write(CInt(I)) Next BW.Close() SW.Stop() End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click SW.Reset() SW.Start() Dim BR As New BinaryReader(File.OpenRead("C:\SS.TXT"), Encoding.UTF8) Dim num As Integer = MAX 'קריאה רצופה For I = 0 To MAX 'קריאה עם דילוג כל פעם 'For I = MAX * 4 To 0 Step -4 ' BR.BaseStream.Position = I ARR(num) = BR.ReadInt32 num -= 1 Next BR.Close() SW.Stop() End Sub
פורסם במקור בפורום CODE613 ב04/07/2013 21:46 (+03:00)
-
@דוד ל.ט.
[u:11abktml]ג. חיפוש תוך כדי הקריאה[/u:11abktml]
כשמחפשים לדוגמה את המילים: שלום {30} ברה {11} הצלה {22} שמח,
אז דבר ראשון נשיג מהמילון את קודי הזיהוי שלהם. לא בצורת מספר, אלא מספר מומר למערך בתים בגודל 4 (עדיף כבר במילון בזיכרון, אבל אם לא עכשיו).
דבר שני נעבור בלולאה של Stream על קובץ האינדקס שמורכב כאמור מסטים של ארבע ארבע בתים.
אז במהלך הלולאה שעוברת על בתי הקובץ (של האינדקס), לבדוק התאמה בין הקטע הנקרא כעת לבין אחד מאבעת הקודים אותם אנו מחפשים.
**[size=85:11abktml]אפשר לעשות את זה תוך כדי (שהקריאה לא תחכה לבדיקה, והבדיקה לא תחכה לקריאה) אבל זה כבר מורכב יותר. אם תאחז בזה אשמח להראות לך איך.[/size:11abktml]**אם נמצאה התאמה פותחים מונה שיבדוק את המרחק בין ההתאמה הזו לזו שאחריה, במידה וזה התאמה לא ראושנה נבדוק את המרחק ונחליט אם יש בהתאמה הוקדמת רלוונטיות לאור המרחק.בקשר לשאילתה שמרשה תווים מיוחדים כמו כוכבית זה מאוד קל ליישם זאת גם, אבל זה שלב נוסף.
טוב, בניתי את המילון והאינדקס כמו שאמרת כעת הגעתי לשלב הקריאה אז איך עושים שהקריאה לא תחכה לבדיקה, והבדיקה לא תחכה לקריאה ?
עוד דבר למעשה השאילתא קצת יותר מורכבת היא יכולה להראות כך:
+שלום/שפע# {30} ברה {11} הצלה/רווח {22} שמח/מאושר/עליז/רוקדכאשר סימן הפלוס מיצג קידומות דיקדוקיות סימן הסולמית מיצג סיומות דיקדוקיות והקוים הנטויים כוונתו או מילה הזאת או הזאת וכו'.
בשיטה שלי הכל עובד מצויין איך עושים את זה בשיטה שלך?פורסם במקור בפורום CODE613 ב05/07/2013 16:39 (+03:00)