Помогите редактировать код, чтобы исправить ошибку «Список аргументов слишком длинный» - PullRequest
0 голосов
/ 19 июня 2011

В настоящее время я провожу некоторое тестирование с новым дополнением к итератору разрыва на основе словаря ICU.У меня есть код, который позволяет мне проверять разрыв слов в текстовом документе, но когда текстовый документ слишком большой, он выдает ошибку: bash: ./a.out: список аргументов слишком длинный

Я не являюсьУбедитесь, как отредактировать код, чтобы разбить список аргументов, когда он становится слишком длинным, чтобы через код можно было запустить файл любого размера.Автор оригинального кода довольно занят, кто-нибудь захочет помочь?

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

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

Код выглядит следующим образом:

/*
Written by George Rhoten to test how word segmentation works.
Code inspired by the break ICU sample.

Here is an example to run this code under Cygwin.

PATH=$PATH:icu-test/source/lib ./a.exe "`cat input.txt`" > output.txt

Encode input.txt as UTF-8.
The output text is UTF-8.
*/

#include <stdio.h>
#include <unicode/brkiter.h>
#include <unicode/ucnv.h>

#define ZW_SPACE "\xE2\x80\x8B"

void printUnicodeString(const UnicodeString &s) {
    int32_t len = s.length() * U8_MAX_LENGTH + 1;
    char *charBuf = new char[len];
    len = s.extract(0, s.length(), charBuf, len, NULL);
    charBuf[len] = 0;
    printf("%s", charBuf);
    delete charBuf;
}

/* Creating and using text boundaries */
int main(int argc, char **argv)
{
    ucnv_setDefaultName("UTF-8");
    UnicodeString stringToExamine("Aaa bbb ccc. Ddd eee fff.");
    printf("Examining: ");
    if (argc > 1) {
        // Override the default charset.
        stringToExamine = UnicodeString(argv[1]);
        if (stringToExamine.charAt(0) == 0xFEFF) {
            // Remove the BOM
            stringToExamine = UnicodeString(stringToExamine, 1);
        }
    }
    printUnicodeString(stringToExamine);
    puts("");

    //print each sentence in forward and reverse order
    UErrorCode status = U_ZERO_ERROR;
    BreakIterator* boundary = BreakIterator::createWordInstance(NULL, status);
    if (U_FAILURE(status)) {
        printf("Failed to create sentence break iterator. status = %s", 
            u_errorName(status));
        exit(1);
    }

    printf("Result:    ");
    //print each word in order
    boundary->setText(stringToExamine);
    int32_t start = boundary->first();
    int32_t end = boundary->next();
    while (end != BreakIterator::DONE) {
        if (start != 0) {
            printf(ZW_SPACE);
        }
        printUnicodeString(UnicodeString(stringToExamine, start, end-start));
        start = end;
        end = boundary->next();
    }

    delete boundary;

    return 0;
}

Большое спасибо!* 1012 Натан *

Ответы [ 2 ]

1 голос
/ 19 июня 2011

Сообщение об ошибке Argument list too long приходит из оболочки bash и происходит еще до того, как ваш код начнет выполняться.

Единственный код, который вы можете исправить, чтобы устранить эту проблему, это исходный код bash (или, возможно, он находится в ядре), а затем вы всегда будете сталкиваться с ограничением.Если вы увеличите с 2048 файлов в командной строке до 10 000, то однажды вам нужно будет обработать 10 001 файлов; -)

Существует множество решений для управления «слишком большими» списками аргументов.

Стандартизированным решением является утилита xargs.

 find / -print | xargs echo 

- бесполезный, но рабочий пример.

См. Как правильно использовать "xargs"когда список аргументов слишком длинный для получения дополнительной информации.

Даже у xargs есть проблемы, потому что имена файлов могут содержать пробелы, символы новой строки и другие недружественные вещи.

Я надеюсь, что этопомогает.

0 голосов
/ 19 июня 2011

Приведенный ниже код считывает содержимое файла, имя которого указано в качестве первого параметра в командной строке, и помещает его в str::buffer.Затем вместо вызова функции UnicodeString с argv[1] используйте этот буфер.

#include<iostream>
#include<fstream>

using namespace std;

int main(int argc, char **argv)
{
    std::string buffer;

    if(argc > 1) {
        std::ifstream t;
        t.open(argv[1]);
        std::string line;
        while(t){
            std::getline(t, line);
            buffer += line + '\n';
        }
    }
    cout << buffer;
    return 0;
}

Обновление:

Ввод в UnicodeStringchar*.Функция GetFileIntoCharPointer делает это.Обратите внимание, что только самая элементарная проверка ошибок реализована ниже!

#include<iostream>
#include<fstream>

using namespace std;

char * GetFileIntoCharPointer(char *pFile, long &lRet)
{
    FILE * fp = fopen(pFile,"rb");
    if (fp == NULL) return 0;

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *pData = new char[size + 1];
    lRet = fread(pData, sizeof(char), size, fp);

    fclose(fp);

    return pData;
}

int main(int argc, char **argv)
{
    long Len;
    char * Data = GetFileIntoCharPointer(argv[1], Len);
    std::cout << Data << std::endl;

    if (Data != NULL)
        delete [] Data;

    return 0;
}
...