当前位置: 首页 > 知识库问答 >
问题:

使用Spring批处理将文件解密到流中,转换并加密为文件

巫马瀚漠
2023-03-14

目的-解密一个.PGP加密的文件,读取数据作为流,执行转换到供应商的要求,加密作为流和写入一个文件。

逻辑-自定义读取器、写入器和任务程序,将解密/加密的数据存储到ExecutionContext并传递到不同的步骤。

适用于-小文件(~1MB)

面临问题-尝试使用(~10MB-10K记录)-读取步骤成功,但当开始将数据作为加密文件写入时-内存问题-Java.lang.OutOfMemoryError:Java堆空间

<job id="testJob" xmlns="http://www.springframework.org/schema/batch">

    <!-- Read Encrypted file and Decrypt -->
    <batch:step id="decryptFile" next="readAndWriteData">
        <batch:tasklet ref="fileDecryptionTasklet">
            <batch:listeners>
                <batch:listener ref="decryptFileListener" />
            </batch:listeners>
        </batch:tasklet>
    </batch:step>

    <!-- Read data from decryption step and write to Stream -->
    <batch:step id="readAndWriteData" next="encryptFile">
        <batch:tasklet>
            <batch:chunk reader="hrdsCustomReader" processor="Processor"
                writer="CustomWriter" commit-interval="${.ftp.comit.interval}" />
            <batch:listeners>
                <batch:listener ref="encryptFileListener" />
            </batch:listeners>
        </batch:tasklet>
    </batch:step>

    <!-- Write to vendor specific file -->
    <batch:step id="encryptFile">
        <batch:tasklet ref="fileEncryptionTasklet" />
    </batch:step>

</job>

@Override
public String read() throws Exception, UnexpectedInputException,
        ParseException {

    decryptedData = (String) stepExecution.getJobExecution()
            .getExecutionContext().get("DecryptedData");
    if (decryptedData != null)
        //logger.info("decryptedData in Custom Reader - \n" + decryptedData);

    stepExecution.getJobExecution().getExecutionContext()
            .put("DecryptedData", null);
    return decryptedData;
}

 
public void write(List items) throws Exception {
    logger.info("Begin writing data as an Encrypted File");

      Iterator itr = items.iterator();
      while(itr.hasNext()) {
             String element =  itr.next();
             lineBuffer.append(element+LINE_SEPARATOR);
          }
      ExecutionContext stepContext = this.stepExecution.getExecutionContext();
        stepContext.put("EncryptedData", lineBuffer);
}


public RepeatStatus execute(StepContribution step, ChunkContext chunk)
        throws Exception {

    InputStream inputstream = new FileInputStream(inputdirectory);

    Message encryptMessage = MessageBuilder
            .withPayload(inputstream)
            .setHeader(
                    FileEncryptionTransformer.ENCRYPTION_OPERATION_HEADER,
                    "decryptAndVerify")
            .setHeader(
                    FileEncryptionTransformer.ENCRYPTION_OPERATION_HEADER,
                    EncryptionUtil.DECRYPT_STREAM_OPERATION)
            .setHeader(FileEncryptionTransformer.SOURCE_FILE_NAME_HEADER,
                    filename).build();

    InputStream inputStream = pgptransformer
            .doTransformStream(encryptMessage);
    String strData = IOUtils.toString(inputStream, "UTF-8");
    inputstream.close();


    chunk.getStepContext().getStepExecution().getExecutionContext().put("DecryptedData", strData);

    return null;
}


public RepeatStatus execute(StepContribution step, ChunkContext chunk)
        throws Exception {


        lineBuffer = (StringBuffer) chunk.getStepContext()
                .getJobExecutionContext().get("EncryptedData");
        byte[] bytes = lineBuffer.toString().getBytes();
        InputStream inputStream = new ByteArrayInputStream(bytes);

        Message encryptMessage = MessageBuilder
                .withPayload(inputStream)
                .setHeader(PGPFileTransformer.OUTPUT_FILE_FOLDER,
                        outputdirectory)
                .setHeader(
                        FileEncryptionTransformer.ENCRYPTION_OPERATION_HEADER,
                        "signAndEncrypt")
                .setHeader(
                        FileEncryptionTransformer.ENCRYPTION_OPERATION_HEADER,
                        EncryptionUtil.ENCRYPT_STREAM_OPERATION)
                .setHeader(FileEncryptionTransformer.SOURCE_FILE_NAME_HEADER,
                        filename).build();

        pgptransformer.doTransform(encryptMessage);
        inputStream.close();


    chunk.getStepContext().getStepExecution().getExecutionContext().put("EncryptedData", null);

    return null;
}

共有1个答案

翟迪
2023-03-14

能够在2分钟内解密和处理100k条记录。

逻辑-分块处理-200条记录成一行。

在下面张贴代码-

<job id="aic-batch-xxx-ftp" xmlns="http://www.springframework.org/schema/batch">


    <!-- Read data , decrypt , process and write to encrypted file -->
    <batch:step id="readAndWriteData">
        <batch:tasklet>
            <batch:chunk reader="xxxCustomReader" processor="xxxFileProccessor"
                writer="xxxCustomWriter" commit-interval="${aic.batch.xxx.ftp.comit.interval}" />
        </batch:tasklet>
    </batch:step>


</job>
StringBuffer decryptedData = new StringBuffer();
    String strLine = "";

    PGPLib pgp = new PGPLib();
    KeyStore keyStore = new KeyStore("xxx.keystore", "xxx");

    long startTime = System.currentTimeMillis();
    // Read & decrypt File Line By Line
    if ((strLine = bufferedReader.readLine()) != null) {
        strLine = strLine.replace("NEW_LINE", "\r\n");
        decryptedData.append((pgp.decryptString(strLine, keyStore,
                "xxx")));
        long endTime = System.currentTimeMillis();
        logger.debug("Total time taken = " + (endTime - startTime) + " msec");
        return decryptedData;
    }
    else
        return null;
public void write(List<? extends StringBuffer> items) throws Exception {
    logger.debug("Begin writing data as an Encrypted File");

    @SuppressWarnings("unchecked")
    Iterator<StringBuffer> itr = (Iterator<StringBuffer>) items.iterator();
    while (itr.hasNext()) {
        StringBuffer element = itr.next();
        encrypt(element);
        count++;
    }
}

public void encrypt(StringBuffer element) throws PGPException, IOException {

    PGPLib pgp = new PGPLib();
    KeyStore keyStore = new KeyStore("xxx.keystore", "xxx");

    String strLine = element.toString();
    StringBuffer buffer = new StringBuffer("");
    int i = 0;
    long startTime = System.currentTimeMillis();

    if (i % 200 == 0) {
        if (i != 0) {
            String encryptString = pgp.encryptString(buffer.toString(),
                    keyStore,
                    "xxx");
            encryptString = encryptString.replace("\r\n", "NEW_LINE");
            bufferedWriter.write(encryptString);
            bufferedWriter.newLine();
        }
        buffer = new StringBuffer(strLine);
    } else {
        buffer.append("\r\n").append(strLine);
    }
    i++;
    if (buffer != null && buffer.length() > 0) {
        String encryptString = pgp.encryptString(buffer.toString(),
                keyStore, "xxx");
        encryptString = encryptString.replace("\r\n", "NEW_LINE");
        bufferedWriter.write(encryptString);
        bufferedWriter.newLine();
    }

    long endTime = System.currentTimeMillis();
    logger.debug("Total time taken = " + (endTime - startTime) + " msec");

}
 类似资料:
  • 问题内容: 下面的加密功能似乎起作用,因为它似乎可以加密文件并将其放置在预期的目录中。我现在正在尝试解密文件,并且它只死于消息“无法完成解密”(在此处进行编码…)。php错误日志中没有任何内容,因此我不确定为什么它会失败,但由于mcrypt对我来说是全新的,所以我更倾向于相信自己在这里做错了… 功能如下: 问题答案: 由于mcrypt是一种废弃软件,不再建议使用,因此这里是使用openssl的示例

  • 我正试图用Spring批处理读取带有日期的CSV文件,但在将日期解析为对象时遇到了麻烦: 对象“target”中字段“date”出现字段错误:拒绝值[2017-07-20 04:15:25.0];代码[TypeMismatch.target.date,TypeMismatch.date,TypeMismatch.java.time.LocalDateTime,TypeMismatch];参数[or

  • 问题内容: 我有一个名为’filename.txt.pgp’的PGP文件,需要解密。当我从命令行运行解密时,它仅询问我密码。我使用gpg命令: 密码足够,我的文件已解密。我可以阅读它的内容。 现在,我应该用Java创建一个实用程序。经过研究,我发现Bouncy Castle图书馆是我最好的选择。但是我可以找到的所有Java示例都使用我没有的公共/专用密钥文件。 您能帮我举一个Java示例,该示例仅

  • 我不完全确定我该做什么了。我一直在网上到处乱翻东西,通读例子,但它们似乎都是如何加密一整个文件,或者只是加密一段数据,除了立即再次解密之外什么也不做。我该如何处理逐行书写?

  • 我正在尝试转换用ActionScript编写的加密/解密程序,并找到它的PHP等价物。编写动作脚本代码的开发人员告诉我,他使用了“TEA”算法来做这件事,但我不再与他联系。当我搜索等效的TEA算法并运行它时,不幸的是,我得到的结果与ActionScript的结果不同。有人能帮我吗?提前感谢。 我在这里粘贴了动作脚本代码。 我开始将其转换为PHP,这就是我所拥有的,但是它不起作用(它给我的加密字符串

  • 我有一个商业案例,使用Spring batch将多个csv文件(每个文件大约1000个,包含1000条记录)合并成单个csv。 请帮助我提供方法和性能方面的指导和解决方案。 到目前为止,我已经尝试了两种方法, 方法1。 Tasklet chunk与multiResourceItemReader一起从目录中读取文件,FlatFileItemWriter作为项目编写器。 这里的问题是,它的处理速度非常