Станьте последними 10 строк файла очень крупного текста> 10 ГБ

Ошибка синтаксиса: ошибка синтаксиса, неожиданный T_ENCAPSED_AND_WHITESPACE

Эта ошибка чаще всего встречается при попытке ссылаться на значение массива с помощью ключевого слова для интерполяции внутри строки с двумя кавычками , когда вся конструкция комплексной переменной не заключена в {}.

Случай ошибки:

Это приведет к Unexpected T_ENCAPSED_AND_WHITESPACE:

echo "This is a double-quoted string with a quoted array key in $array['key']";
//---------------------------------------------------------------------^^^^^

Возможные исправления:

В строке с двойными кавычками PHP разрешает использовать строки ключей ключей без кавычек и не выдаст E_NOTICE. Таким образом, вышесказанное может быть записано как:

echo "This is a double-quoted string with an un-quoted array key in $array[key]";
//------------------------------------------------------------------------^^^^^

Вся сложная переменная массива и ключ (ы) могут быть заключены в {}, и в этом случае они должны быть указаны чтобы избежать E_NOTICE. Документация PHP рекомендует этот синтаксис для сложных переменных.

echo "This is a double-quoted string with a quoted array key in {$array['key']}";
//--------------------------------------------------------------^^^^^^^^^^^^^^^
// Or a complex array property of an object:
echo "This is a a double-quoted string with a complex {$object->property->array['key']}";

Конечно, альтернатива любой из вышеперечисленного заключается в объединении переменной массива in вместо интерполировать его:

echo "This is a double-quoted string with an array variable " . $array['key'] . " concatenated inside.";
//----------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^

Для справки см. раздел «Переменная синтаксический анализ» в странице руководства PHP Strings

64
задан slugster 14 December 2015 в 23:59
поделиться

16 ответов

Читайте до конца файла, затем ищите назад, пока Вы не найдете десять новых строк, и затем считаете вперед до конца учет различной кодировки. Обязательно обработайте случаи, где количество строк в файле - меньше чем десять. Ниже реализация (в C#, когда Вы отметили это), обобщенный для нахождения последнего numberOfTokens в файле расположенным в path закодированный в encoding, где маркерный разделитель представлен tokenSeparator; результат возвращается как string (это могло быть улучшено путем возврата IEnumerable<string>, который перечисляет маркеры).

public static string ReadEndTokens(string path, Int64 numberOfTokens, Encoding encoding, string tokenSeparator) {

    int sizeOfChar = encoding.GetByteCount("\n");
    byte[] buffer = encoding.GetBytes(tokenSeparator);


    using (FileStream fs = new FileStream(path, FileMode.Open)) {
        Int64 tokenCount = 0;
        Int64 endPosition = fs.Length / sizeOfChar;

        for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar) {
            fs.Seek(-position, SeekOrigin.End);
            fs.Read(buffer, 0, buffer.Length);

            if (encoding.GetString(buffer) == tokenSeparator) {
                tokenCount++;
                if (tokenCount == numberOfTokens) {
                    byte[] returnBuffer = new byte[fs.Length - fs.Position];
                    fs.Read(returnBuffer, 0, returnBuffer.Length);
                    return encoding.GetString(returnBuffer);
                }
            }
        }

        // handle case where number of tokens in file is less than numberOfTokens
        fs.Seek(0, SeekOrigin.Begin);
        buffer = new byte[fs.Length];
        fs.Read(buffer, 0, buffer.Length);
        return encoding.GetString(buffer);
    }
}
76
ответ дан jason 24 November 2019 в 15:46
поделиться

Почему бы не использовать file.readalllines, который возвращает строку []?

Тогда можно получить последние 10 строк (или члены массива), который был бы тривиальной задачей.

Этот подход не принимает во внимание проблем кодирования, и я не уверен в точной эффективности этого подхода (время, потраченное для завершения метода, и т.д.).

-11
ответ дан GurdeepS 24 November 2019 в 15:46
поделиться

Откройте файл и начните читать строки. После чтения 10 строк, открытых другой указатель, запускающийся впереди файла, таким образом, второй указатель изолирует первое 10 строками. Продолжайте читать, перемещая эти два указателя в унисон, до первых пределов конец файла. Тогда используйте второй указатель для чтения результата. Это работает с любым файлом размера включая пустой и более короткое, чем длина хвоста. И легко корректироваться для любой длины хвоста. Недостаток, конечно, состоит в том, что Вы заканчиваете тем, что читали весь файл, и это может быть точно, чего Вы стараетесь избегать.

0
ответ дан Sisiutl 24 November 2019 в 15:46
поделиться

Я думаю, что другие плакаты все показали, что нет никакого реального ярлыка.

можно или использовать инструмент, такой как хвост (или powershell), или можно записать некоторый немой код, который ищет конец файла и затем оглядывается назад для n новых строк.

существует много реализаций хвоста там в сети - смотрят на исходный код, чтобы видеть, как они делают это. Хвост довольно эффективен (даже на очень очень больших файлах) и таким образом, у них должен быть он право, когда они записали его!

1
ответ дан Fortyrunner 24 November 2019 в 15:46
поделиться

Если Вы открываете файл с FileMode. Добавьте его, будет искать до конца файла Вас. Тогда Вы могли искать назад число байтов, Вы хотите и читаете их. Это не могло бы быть быстро, хотя независимо от того, что Вы делаете, так как это - довольно крупный файл.

1
ответ дан Steven Behnke 24 November 2019 в 15:46
поделиться

Один полезный метод FileInfo.Length. Это дает размер файла в байтах.

, Какая структура является Вашим файлом? Вы уверены, что последние 10 строк будут около конца файла? Если у Вас будет файл с 12 строками текста и 10 ГБ 0s, то рассмотрение конца действительно не будет этим быстро. С другой стороны Вам, возможно, придется просмотреть целый файл.

, Если Вы уверены, что файл содержит многочисленные короткие строки каждый на новой строке, ищите до конца, затем перепроверьте, пока Вы не считали 11 концов строк. Тогда можно читать вперед для следующих 10 строк.

1
ответ дан biozinc 24 November 2019 в 15:46
поделиться

Вы могли использовать версию для Windows хвост команда, и просто pype это производится к текстовому файлу с> символ, или просмотрите его на экране в зависимости от того, каковы Ваши потребности.

2
ответ дан Jared 24 November 2019 в 15:46
поделиться

Я думаю, что следующий код решит prblem с тонкой переаттестацией изменений, кодирующей

StreamReader reader = new StreamReader(@"c:\test.txt"); //pick appropriate Encoding
reader.BaseStream.Seek(0, SeekOrigin.End);
int count = 0;
while ((count < 10) && (reader.BaseStream.Position > 0))
{
    reader.BaseStream.Position--;
    int c = reader.BaseStream.ReadByte();
    if (reader.BaseStream.Position > 0)
        reader.BaseStream.Position--;
    if (c == Convert.ToInt32('\n'))
    {
        ++count;
    }
}
string str = reader.ReadToEnd();
string[] arr = str.Replace("\r", "").Split('\n');
reader.Close();
4
ответ дан Peter Lacerenza 24 November 2019 в 15:46
поделиться

Именно это делает команда хвоста Unix. См. http://en.wikipedia.org/wiki/Tail_ (Unix)

существует много реализаций с открытым исходным кодом в Интернете и здесь один для win32: Хвост для WIn32

4
ответ дан zendar 24 November 2019 в 15:46
поделиться

Я не уверен, насколько эффективный это будет, но в Windows PowerShell, получая последние десять строк файла так же легко как

Get-Content file.txt | Select-Object -last 10
6
ответ дан Eric Ness 24 November 2019 в 15:46
поделиться

Необходимо быть в состоянии использовать FileStream. Ищите () , чтобы переместиться до конца файла, затем проложить себе путь назад, ища \n, пока у Вас не будет достаточного количества строк.

6
ответ дан Lolindrath 24 November 2019 в 15:46
поделиться

Как другие предположили, можно пойти до конца файла и читать назад, эффективно. Однако это немного хитро - особенно, потому что, если у Вас есть кодирование переменной длины (такое как UTF-8) необходимо быть хитростью о проверке, что Вы получаете "целые" символы.

17
ответ дан Jon Skeet 24 November 2019 в 15:46
поделиться

Я, вероятно, просто открыл бы его как двоичный поток, искал бы до конца, затем обратно ища разрывы строки. Создайте резервную копию 10 (или 11 в зависимости от той последней строки) для нахождения 10 строк, тогда просто читайте до конца и Кодирование использования. GetString на том, что Вы читаете для получения его в формат строки. Разделение, как желаемый.

22
ответ дан ctacke 24 November 2019 в 15:46
поделиться

Хвост? Хвост является командой Unix, которая отобразит последние несколько строк файла. Существует версия Windows в набор ресурса Windows 2003 Server .

17
ответ дан w4g3n3r 24 November 2019 в 15:46
поделиться

Я использовал этот код для маленькой утилиты когда-то назад, я надеюсь, что он может помочь Вам!

private string ReadRows(int offset)     /*offset: how many lines it reads from the end (10 in your case)*/
{
    /*no lines to read*/
    if (offset == 0)
        return result;

    using (FileStream fs = new FileStream(FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 2048, true))
    {
        List<char> charBuilder = new List<char>(); /*StringBuilder doesn't work with Encoding: example char                   
0
ответ дан 24 November 2019 в 15:46
поделиться

Если у вас есть файл с четным форматом на строку (например, система daq), вы просто используйте streamreader, чтобы получить длину файла, затем возьмите одну из строк ( readline () ).

Разделите общую длину на длину строки. Теперь у вас есть общее длинное число, представляющее количество строк в файле.

Ключ в том, что вы используете readline () до получения данных для вашего массива или чего-то еще. Это гарантирует, что вы начнете с начала новой строки и не получите каких-либо данных, оставшихся от предыдущей.

StreamReader leader = new StreamReader(GetReadFile);
leader.BaseStream.Position = 0;
StreamReader follower = new StreamReader(GetReadFile);

int count = 0;
string tmper = null;
while (count <= 12)
{
    tmper = leader.ReadLine();
    count++;
}

long total = follower.BaseStream.Length; // get total length of file
long step = tmper.Length; // get length of 1 line
long size = total / step; // divide to get number of lines
long go = step * (size - 12); // get the bit location

long cut = follower.BaseStream.Seek(go, SeekOrigin.Begin); // Go to that location
follower.BaseStream.Position = go;

string led = null;
string[] lead = null ;
List<string[]> samples = new List<string[]>();

follower.ReadLine();

while (!follower.EndOfStream)
{
    led = follower.ReadLine();
    lead = Tokenize(led);
    samples.Add(lead);
}
0
ответ дан 24 November 2019 в 15:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: