0

我目前正在对基于 ICU 字典的中断迭代器的新增功能进行一些测试。我的代码允许我测试文本文档的断词,但是当文本文档太大时,它会给出错误:bash: ./a.out: Argument list too long

我不确定如何编辑代码以在参数列表太长时分解参数列表,以便可以通过代码运行任何大小的文件。原代码作者很忙,有人愿意帮忙吗?

我尝试删除正在检查的内容的打印以查看是否有帮助,但我仍然在大文件上遇到错误(不需要打印正在检查的内容 - 我只需要结果)。

如果可以修改代码以逐行读取源文本文件并将结果逐行导出到另一个文本文件(完成后以所有行结束),那将是完美的。

代码如下:

/*
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;
}

非常感谢!-内森

4

2 回答 2

1

错误消息来自Argument list too longbash shell,并且发生在您的代码甚至开始执行之前。

您可以修复以消除此问题的唯一代码是 bash 源代码(或者它可能在内核中),然后,您总是会遇到限制。如果您从命令行上的 2048 个文件增加到 10,000 个,那么有一天您将需要处理 10,001 个文件;-)

管理“太大”的参数列表有很多解决方案。

标准化的解决方案是 xargs 实用程序。

 find / -print | xargs echo 

是一个无用但有效的例子。

有关详细信息,请参阅当参数列表太长时如何正确使用“xargs”

甚至 xargs 也有问题,因为文件名可能包含空格、换行符和其他不友好的东西。

我希望这有帮助。

于 2011-06-19T13:55:26.363 回答
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;
}

更新:

输入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;
}
于 2011-06-19T15:41:56.887 回答