À L'Aide De FileStream.Chercher

Je suis en train de travailler avec FileStream.Chercher à aller rapidement à une ligne et de le lire.

Cependant, je ne suis pas d'obtenir les résultats de la droite. J'ai essayé de regarder cela pendant un certain temps et ne peut pas comprendre ce que je fais de mal.

Environnement:

Système d'exploitation: Windows 7

Cadre: .NET 4.0

IDE: Visual C# Express 2010

Échantillon de Données dans le fichier de localisation: C:\Temp\Temp.txt

0001/100!2500 
0002/100!2500 
0003/100!2500 
0004/100!2500 
0005/100!2500 
0006/100!2500 
0007/100!2500 
0008/100!2500 
0009/100!2500 
0010/100!2500 

Le code:

class PaddedFileSearch
{
private int LineLength { get; set; }
private string FileName { get; set; }
public PaddedFileSearch()
{
FileName = @"C:\Temp\Temp.txt";     //This is a padded file.  All lines are of the same length.
FindLineLength();
Debug.Print("File Line length: {0}", LineLength);
//TODO: This purely for testing.  Move this code out.
SeekMethod(new int[] { 5, 3, 4 });
/*  Expected Results:
*  Line No     Position        Line
*  -------     --------        -----------------
*  3           30              0003|100!2500
*  4           15              0004|100!2500
*  5           15              0005|100!2500 -- This was updated after the initial request.
*/
/* THIS DOES NOT GIVE THE EXPECTED RESULTS */
SeekMethod(new int[] { 5, 3 });
/*  Expected Results:
*  Line No     Position        Line
*  -------     --------        -----------------
*  3           30              0003|100!2500
*  5           30              0005|100!2500
*/
}
private void FindLineLength()
{
string line;
//Add check for FileExists
using (StreamReader reader = new StreamReader(FileName))
{
if ((line = reader.ReadLine()) != null)
{
LineLength = line.Length + 2;
//The 2 is for NewLine(\r\n)
}
}
}
public void SeekMethod(int[] lineNos)
{
long position = 0;
string line = null;
Array.Sort(lineNos);
Debug.Print("");
Debug.Print("Line No\t\tPosition\t\tLine");
Debug.Print("-------\t\t--------\t\t-----------------");
using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
using (StreamReader reader = new StreamReader(fs))
{
foreach (int lineNo in lineNos)
{
position = (lineNo - 1) * LineLength - position;
fs.Seek(position, SeekOrigin.Current);
if ((line = reader.ReadLine()) != null)
{
Debug.Print("{0}\t\t\t{1}\t\t\t\t{2}", lineNo, position, line);
}
}
}
}
}
}

La sortie j'obtiens:

Fichier de la longueur de la Ligne: 15 
Pas De Position De La Ligne De 
------- -------- ----------------- 
3 30 0003/100!2500 
4 15 0004/100!2500 
5 45 0005/100!2500 
Pas De Position De La Ligne De 
------- -------- ----------------- 
3 30 0003/100!2500 
5 30 0004/100!2500 

Mon problème est avec la sortie suivante:

Ligne Pas De Poste En Ligne 
------- -------- ----------------- 
5 30 0004/100!2500 

La sortie de la Ligne doit être: 0005/100!2500

Je ne comprends pas pourquoi ce qui se passe.

Je fais quelque chose de mal?
Est-il une solution?
Aussi y at-il des façons plus rapides pour ce faire, utilisez quelque chose comme chercher?

(Je suis à la recherche pour le code en fonction des options et des PAS Oracle ou SQL Server. Pour la clarté de l'exposé permet de dire aussi que la taille du fichier de 1 GO.)

Toute aide est grandement appréciée.

Grâce.

Mise à JOUR:

J'ai trouvé 4 grandes réponses ici. Merci beaucoup.

Échantillon Horaires:

Basé sur les quelques pistes suivantes sont les méthodes de meilleur pour de bon. Même le bon est très proche des meilleurs.

Dans un fichier qui contient 10K lignes, 2.28 MB. J'ai cherché pour le même 5000 lignes au hasard à l'aide de toutes les options.

  1. Seek4: Temps écoulé: 00:00:00.0398530 ms -- Ritch Melton
  2. Seek3: Temps écoulé: 00:00:00.0446072 ms -- Valentin Kuzub
  3. Seek1: Temps écoulé: 00:00:00.0538210 ms -- Jake
  4. Seek2: Temps écoulé: 00:00:00.0889589 ms -- bitxwise

Indiqué ci-dessous est le code. Après l'enregistrement du code, vous pouvez simplement appeler en tapant TestPaddedFileSeek.CallPaddedFileSeek();. Vous devrez également spécifier l'espace de noms et le "à l'aide de références".

`

///<summary>
///This class multiple options of reading a by line number in a padded file (all lines are the same length).
///The idea is to quick jump to the file.
///Details about the discussions is available at: http://stackoverflow.com/questions/5201414/having-a-problem-while-using-filestream-seek-in-c-solved
///</summary>
class PaddedFileSeek
{
public FileInfo File {get; private set;}
public int LineLength { get; private set; }
#region Private methods
private static int FindLineLength(FileInfo fileInfo)
{
using (StreamReader reader = new StreamReader(fileInfo.FullName))
{
string line;
if ((line = reader.ReadLine()) != null)
{
int length = line.Length + 2;   //The 2 is for NewLine(\r\n)
return length;
}
}
return 0;
}
private static void PrintHeader()
{
/*
Debug.Print("");
Debug.Print("Line No\t\tLine");
Debug.Print("-------\t\t--------------------------");
*/ 
}
private static void PrintLine(int lineNo, string line)
{
//Debug.Print("{0}\t\t\t{1}", lineNo, line);
}
private static void PrintElapsedTime(TimeSpan elapsed)
{
Debug.WriteLine("Time elapsed: {0} ms", elapsed);
}
#endregion
public PaddedFileSeek(FileInfo fileInfo)
{
//Possibly might have to check for FileExists
int length = FindLineLength(fileInfo);
//if (length == 0) throw new PaddedProgramException();
LineLength = length;
File = fileInfo;
}
public void CallAll(int[] lineNoArray, List<int> lineNoList)
{
Stopwatch sw = new Stopwatch();
#region Seek1
//Create new stopwatch
sw.Start();
Debug.Write("Seek1: ");
//Print Header
PrintHeader();
Seek1(lineNoArray);
//Stop timing
sw.Stop();
//Print Elapsed Time
PrintElapsedTime(sw.Elapsed);
sw.Reset();
#endregion
#region Seek2
//Create new stopwatch
sw.Start();
Debug.Write("Seek2: ");
//Print Header
PrintHeader();
Seek2(lineNoArray);
//Stop timing
sw.Stop();
//Print Elapsed Time
PrintElapsedTime(sw.Elapsed);
sw.Reset();
#endregion
#region Seek3
//Create new stopwatch
sw.Start();
Debug.Write("Seek3: ");
//Print Header
PrintHeader();
Seek3(lineNoArray);
//Stop timing
sw.Stop();
//Print Elapsed Time
PrintElapsedTime(sw.Elapsed);
sw.Reset();
#endregion
#region Seek4
//Create new stopwatch
sw.Start();
Debug.Write("Seek4: ");
//Print Header
PrintHeader();
Seek4(lineNoList);
//Stop timing
sw.Stop();
//Print Elapsed Time
PrintElapsedTime(sw.Elapsed);
sw.Reset();
#endregion
}
///<summary>
///Option by Jake
///</summary>
///<param name="lineNoArray"></param>
public void Seek1(int[] lineNoArray)
{
long position = 0;
string line = null;
Array.Sort(lineNoArray);
using (FileStream fs = new FileStream(File.FullName, FileMode.Open, FileAccess.Read, FileShare.None))
{
using (StreamReader reader = new StreamReader(fs))
{
foreach (int lineNo in lineNoArray)
{
position = (lineNo - 1) * LineLength;
fs.Seek(position, SeekOrigin.Begin);
if ((line = reader.ReadLine()) != null)
{
PrintLine(lineNo, line);
}
reader.DiscardBufferedData();
}
}
}
}
///<summary>
///option by bitxwise
///</summary>
public void Seek2(int[] lineNoArray)
{
string line = null;
long step = 0;
Array.Sort(lineNoArray);
using (FileStream fs = new FileStream(File.FullName, FileMode.Open, FileAccess.Read, FileShare.None))
{
//using (StreamReader reader = new StreamReader(fs))
//If you put "using" here you will get WRONG results.
//I would like to understand why this is.
{
foreach (int lineNo in lineNoArray)
{
StreamReader reader = new StreamReader(fs);
step = (lineNo - 1) * LineLength - fs.Position;
fs.Position += step;
if ((line = reader.ReadLine()) != null)
{
PrintLine(lineNo, line);
}
}
}
}
}
///<summary>
///Option by Valentin Kuzub
///</summary>
///<param name="lineNoArray"></param>
#region Seek3
public void Seek3(int[] lineNoArray)
{
long position = 0; //totalPosition = 0;
string line = null;
int oldLineNo = 0;
Array.Sort(lineNoArray);
using (FileStream fs = new FileStream(File.FullName, FileMode.Open, FileAccess.Read, FileShare.None))
{
using (StreamReader reader = new StreamReader(fs))
{
foreach (int lineNo in lineNoArray)
{
position = (lineNo - oldLineNo - 1) * LineLength;
fs.Seek(position, SeekOrigin.Current);
line = ReadLine(fs, LineLength);
PrintLine(lineNo, line);
oldLineNo = lineNo;
}
}
}
}
#region Required Private methods
///<summary>
///Currently only used by Seek3
///</summary>
///<param name="stream"></param>
///<param name="length"></param>
///<returns></returns>
private static string ReadLine(FileStream stream, int length)
{
byte[] bytes = new byte[length];
stream.Read(bytes, 0, length);
return new string(Encoding.UTF8.GetChars(bytes));
}
#endregion
#endregion
///<summary>
///Option by Ritch Melton
///</summary>
///<param name="lineNoArray"></param>
#region Seek4
public void Seek4(List<int> lineNoList)
{
lineNoList.Sort();
using (var fs = new FileStream(File.FullName, FileMode.Open))
{
lineNoList.ForEach(ln => OutputData(fs, ln));
}
}
#region Required Private methods
private void OutputData(FileStream fs, int lineNumber)
{
var offset = (lineNumber - 1) * LineLength;
fs.Seek(offset, SeekOrigin.Begin);
var data = new byte[LineLength];
fs.Read(data, 0, LineLength);
var text = DecodeData(data);
PrintLine(lineNumber, text);
}
private static string DecodeData(byte[] data)
{
var encoding = new UTF8Encoding();
return encoding.GetString(data);
}
#endregion
#endregion
}
static class TestPaddedFileSeek
{
public static void CallPaddedFileSeek()
{
const int arrayLenght = 5000;
int[] lineNoArray = new int[arrayLenght];
List<int> lineNoList = new List<int>();
Random random = new Random();
int lineNo;
string fileName;
fileName = @"C:\Temp\Temp.txt";
PaddedFileSeek seeker = new PaddedFileSeek(new FileInfo(fileName));
for (int n = 0; n < 25; n++)
{
Debug.Print("Loop no: {0}", n + 1);
for (int i = 0; i < arrayLenght; i++)
{
lineNo = random.Next(1, arrayLenght);
lineNoArray[i] = lineNo;
lineNoList.Add(lineNo);
}
seeker.CallAll(lineNoArray, lineNoList);
lineNoList.Clear();
Debug.Print("");
}
}
}

`

  • Êtes-vous code manquant? Je ne vois pas votre fichier en lecture/recherche partie
  • C'est là, dans la SeekMethod méthode.
  • Je ne comprends pas votre position. Si la ligne 1 est 0, 2, 15, 3, 30, 4 est de 45(15?), 5 est de 60 (au lieu de 30?) - il correct?
  • Vous êtes de droite. J'étais tellement concentrée sur la LIGNE de résultat, je n'ai même pas remarqué.
InformationsquelleAutor Pranav Shah | 2011-03-05