2011-06-19 3 views
0

В настоящее время я тестирую новое дополнение к итератору на основе словаря на основе словаря 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; 
} 

спасибо! -Nathan

+0

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

+1

Я случайно удалил свой комментарий :-) Чтобы прочитать файл в C++, см. Http://www.cplusplus.com/doc/tutorial/files/, разместите свой код, и я буду рад помочь вам ... –

+0

Мне было интересно, куда это пошло :) В этом вопросе нуждается код, который нуждается в модификации для чтения по строкам. Я лично не знаю C++ - оригинальный код был создан кем-то, помогающим мне с подачей ICU, но он довольно занят, поэтому я думал, что буду искать в другом месте. Спасибо за вашу помощь! – Nathan

ответ

0

Код ниже читает содержимое файла, имя которого указано в качестве первого параметра в командной строке и помещает его в 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; 
} 

Update:

Вклад в UnicodeString должен быть char*. Функция 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; 
} 
+0

Спасибо Fredrik - сможете ли вы заполнить детали немного больше? Я в недоумении ... извините! Вы замените основную функцию int из старого кода кодом? Я пробовал это, но получаю ошибки: InsertZWSlarge.cpp: 80: 5: ошибка: ожидаемый неквалифицированный-id до «if» InsertZWSlarge.cpp: 88: 5: ошибка: «граница» не называет тип InsertZWSlarge.cpp: 91: 5: ошибка: ожидаемый неквалифицированный-id до 'while' Так что я думаю, что я сделал это неправильно ... – Nathan

+0

Hi Again Fredrik! Спасибо за вашу помощь! Извините, мой опыт настолько ограничен, я все еще не могу заставить его работать. Ваш обновленный код заменяет то, что вы писали ранее? Возможно, это проблема совместимости с ICU ... но, скорее, моя глупость: P Вы могли бы добавить свой код в соответствие с кодом, который я разместил в вопросе? Благодаря! – Nathan

1

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

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

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

Стандартизованное решение - утилита xargs.

find/-print | xargs echo 

является не полезным, но рабочим примером.

См. How to use "xargs" properly when argument list is too long для получения дополнительной информации.

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

Надеюсь, это поможет.

Смежные вопросы