使用Java每2小时生成CSV文件 [英] CSV file generation in every 2 hours using Java

查看:380
本文介绍了使用Java每2小时生成CSV文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中要求使用Java程序每2小时生成CSV文件. 我想在基于小时的CSV文件下创建按日期排列的文件夹.这意味着每个CSV文件都包含2小时(可配置)数据.我能够创建每小时的CSV文件.但是我无法创建可配置的每小时CSV.我没有使用ScheduledExecutorService.我想要简单的方法来解决这个问题.

I have a requirement in our project to generate a CSV file every 2 hours using a Java program. I want to create date wise folder under hourly based CSV file.It means every CSV file contains 2 hours(Configurable) data. I am able to create hourly basis CSV file. But i not able to create configurable hourly basis CSV.I am not using ScheduledExecutorService. I want simple way to solve this problem.

public static boolean writeFileHourlyBasis(String tenantName, String clusterName, String contentSourceName,
        String fileContent) {

    String reconciliationLogPath = AppConfigHashMap.getPropertyValue("ReconciliationLogFolder");

    if (reconciliationLogPath != null) {
        File fullReconciliationLogPath = new File(reconciliationLogPath + File.separator + tenantName
                + File.separator + clusterName + File.separator + contentSourceName + File.separator + formatter.format(new Date()));
        if (fullReconciliationLogPath.mkdirs() == true){

            logger.debug("Folder " + fullReconciliationLogPath + " created.");
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("HH");
            String fileName = tenantName + "_" + dateFormat.format(new Date()) + ".csv";
            File file1 = new File(fullReconciliationLogPath, fileName);
            String headerString = "";           

            if (!file1.exists()) {
                headerString = "DateTimeUTC,DateTime,Transcript->TranscriptId,Target->ReturnCode,Target->Status,Target->Message,MessageId,StatusMessage \n";
            }else{
                if(isNewLine){
                    headerString="\n";
                }
                isNewLine=false;
            }
            FileWriter datawriter = new FileWriter(file1, true);
            datawriter.append(headerString);
            datawriter.append(fileContent);
            datawriter.append("\n");
            datawriter.flush();
            datawriter.close();
        } catch (Exception e) {
            logger.warn("Exception occurred while writing Reconcilation log :" + e.getMessage());
            return false;
        }
    }else{
        //TODO: log.error("Reconciliation log enabled, but path not provided!");
        logger.warn("Reconciliation log enabled, but path not provided!");
        return false;
    }
    return true;

}

任何人都可以帮助我解决这个问题.

Can any one help me to solve this problem.

推荐答案

我没有使用ScheduledExecutorService.我想要解决这个问题的简单方法.

I am not using ScheduledExecutorService. I want simple way to solve this problem.

您已经有了答案:将Executors框架添加到Java就是这样简单的方法,以解决此问题.执行者将处理后台任务和线程的棘手的细节弄糟了.

You already have your answer: The Executors framework was added to Java to be that simple way to solve this problem. Executors abstract away the tricky messy details of handling background tasks and threading.

出于您的目的,您应该使用ScheduledExecutorService.

Your should be using a ScheduledExecutorService for your purpose.

执行程序乍看起来似乎令人生畏,但在实践中使用它们非常简单.阅读Oracle教程.然后查看Stack Overflow和其他博客等中的代码示例.

Executors may seem daunting at first glance, but their use in practice is quite simple. Read the Oracle Tutorial. Then look at code examples in Stack Overflow and other blogs etc.

提示:使用外部搜索引擎(如site:StackOverflow.com准则)使用外部搜索引擎(例如DuckDuckGo/Bing/Google)进行搜索堆栈溢出. Stack Overflow中的内置搜索功能是贫乏的,并且偏向于问题"而不是答案".

Tip: Search Stack Overflow using an external search engine such as DuckDuckGo/Bing/Google with the site:StackOverflow.com criterion. The built-in search feature in Stack Overflow is anemic and is biased towards Questions rather than Answers.

定义由线程池支持的执行程序服务.

Define your executor service, backed by a thread pool.

ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

定义要以Runnable身份运行的任务.

Define your task to be run as a Runnable.

Runnable task = new Runnable() {
    @Override
    public void run () {
        … stuff to do goes here
    }
}

Runnable对象传递给执行程序服务.告诉它多久运行一次.您还传递了初始延迟;在这里,我们传递零以立即开始.

Pass the Runnable object to the executor service. Tell it how often to run. You also pass an initial delay; here we pass zero to begin immediately.

scheduledExecutorService.scheduleAtFixedRate( task , 0 , 2 , TimeUnit.HOURS ); 


提示:有关使用ScheduledExecutorService(SES)的两点重要知识:


Tip: Two critical things to know about using ScheduledExecutorService (SES):

  • 在不再需要或您的应用程序退出时,请始终正常关闭SES.否则,线程池可能会像僵尸一样存活并继续工作.
  • 始终在提交给SES的任务中捕获所有异常,甚至是错误.如果有任何异常或错误冒出来到达SES,则SES的所有后续工作都会折皱.停顿是无声的,没有警告,没有日志.

因此,修改上面看到的Runnable.

So modify the Runnable seen above.

Runnable task = new Runnable() {
    @Override
    public void run () {
        try {
            … stuff to do goes here
        } catch ( Exception e ) {
            … Handle any unexpected exceptions bubbling up to avoid silently killing your executor service. 
        }
    }
}


提示:切勿使用可怕的旧日期时间类,例如DateCalendarSimpleDateFormat.几年前,现代的 java.time 类取代了它们.


Tip: Never use the terrible old date-time classes such as Date, Calendar, SimpleDateFormat. They were supplanted years ago by the modern java.time classes.

提示:在文件名中写入时间时,请遵循 ISO 8601 将日期时间值表示为文本的标准.

Tip: When writing a moment in a file name, follow the ISO 8601 standard for representing date-time values as text.

在解析或生成字符串时, java.time 类中默认使用这些格式.

These formats are used by default in the java.time classes when parsing or generating strings.

对于文件名,您可能希望使用标准中定义的替代基本"格式. Basic (基本)表示将分隔符的使用减至最少.

For file names you may want to use the alternative "basic" formats defined in the standard. Basic means the use of delimiters is minimized.

请确保避免使用反斜杠,正斜杠和冒号字符.分别在DOS/Windows,Unix和macOS/iOS文件系统中是禁止使用的.

Be sure to avoid backward slash, forward slash, and colon characters. These are forbidden in DOS/Windows, Unix, and macOS/iOS file systems, respectively.

提示:请勿编写自己的CSV代码.使用 Apache Commons CSV 库读取和写入CSV或制表符分隔的文件.根据我的经验,效果很好.

Tip: Don’t write your own CSV code. Use Apache Commons CSV library to read and write CSV or Tab-delimited files. It works well in my experience.

这是单个.java文件中包含的整个示例.

Here is an entire example contained in a single .java file.

我们有小类Event的一些对象.在每次计划的运行中,我们都会更新每个Event对象的时间戳.然后,我们使用Apache Commons CSV库将所有Event对象的所有成员变量写入CSV格式的文本文件中.每次运行均由Runnable对象定义.

We have a few objects of our little class Event. On each scheduled run, we update the timestamp on each Event object. Then we write all the member variables of all those Event objects to a text file in CSV format using the Apache Commons CSV library. Each run is defined by a Runnable object.

运行由ScheduledExecutorService调度,该线程由具有单个线程的线程池支持.

The runs are scheduled by a ScheduledExecutorService backed by a thread pool with a single thread.

在实际工作中,我不会将所有这些压缩到单个.java文件中.但是在这里这样做可以制作一个不错的紧凑型演示.

In real work I would not squeeze all this into a single .java file. But doing so here makes for a nice compact demo.

package com.basilbourque.example;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ExportToCsv {
    public static void main ( String[] args ) {
        ExportToCsv app = new ExportToCsv();
        app.doIt();
    }

    private void doIt () {
        System.out.println( "TRACE - doIt running at " + ZonedDateTime.now() );
        List< Event > events = List.of(
        new Event( UUID.randomUUID() , "alpha" , Instant.now() ) ,
        new Event( UUID.randomUUID() , "beta" , Instant.now() ) ,
        new Event( UUID.randomUUID() , "gamma" , Instant.now() )
        );

        Runnable task = new Runnable() {
            @Override
            public void run () {
                // Nest all this stuff of your `run` method into a `try-catch( Exception e )` to avoid having your executor cease silently.
                Instant start = Instant.now();
                System.out.print( "TRACE - Runnable starting at " + start + ". " );
                // Update the moment recorded in each `Event` object.
                events.forEach( ( event ) -> event.update() );
                // Export to CSV. Using "Apache Commons CSV" library. https://commons.apache.org/proper/commons-csv/
                // Get current moment in UTC. Lop off the seconds and fractional second. Generate text without delimiters.
                String dateTimeLabel = OffsetDateTime.now( ZoneOffset.UTC ).truncatedTo( ChronoUnit.MINUTES ).format( DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmX" , Locale.US ) );
                String fileNamePath = "myCsv_" + dateTimeLabel + ".csv";
                try (  // Try-with-resources syntax automatically closes any passed objects implementing `AutoCloseable`, even if an exception is thrown.
                BufferedWriter writer = new BufferedWriter( new FileWriter( fileNamePath ) ) ;
                CSVPrinter csvPrinter = new CSVPrinter( writer , CSVFormat.DEFAULT.withHeader( "Id" , "Name" , "When" ) ) ;
                ) {
                    for ( Event event : events ) {
                        csvPrinter.printRecord( event.id , event.name , event.when );
                    }
                    csvPrinter.flush();
                } catch ( IOException e ) {
                    // TODO: Handle i/o exception when creating or writing to file in storage.
                    e.printStackTrace();
                }
                Instant stop = Instant.now() ;
                System.out.println( "Runnable ending its run at " + start + ". Duration: " + Duration.between( start , stop ) + ".");
            }
        };

        // Schedule this task. Currently set to run every two minutes, ending after 20 minutes. Adjust as desired.
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();  // Using a single thread here, as we have only a single series of tasks to be executed, no multi-tasking. 
        try {
            scheduledExecutorService.scheduleAtFixedRate( task , 0 , 2 , TimeUnit.MINUTES );  // Schedule our task to run every so often.
            try {
                Thread.sleep( TimeUnit.MINUTES.toMillis( 20 ) );  // Sleep this main thread for a while to let our task running on the background thread do its thing a few times.
            } catch ( InterruptedException e ) {
                System.out.println( "TRACE - Our main thread was woken earlier than expected, and interrupted our run. " );
                e.printStackTrace();
            }
        } finally {
            System.out.println( "Shutting down the scheduledExecutorService at " + ZonedDateTime.now() );  // Generally best to log in UTC, `Instant.now()`.
            scheduledExecutorService.shutdown();  // Always shutdown your executor, as it may otherwise survive your app exiting, becoming a zombie, continuing to run endlessly.
        }
        System.out.println( "App running on main thread ending at " + Instant.now() + "." );
    }

    class Event {
        public UUID id;
        public String name;
        public Instant when;

        public Event ( UUID id , String name , Instant when ) {
            this.id = id;
            this.name = name;
            this.when = when;
        }

        public void update () {
            this.when = Instant.now();
        }
    }
}

运行时.

TRACE-doIt运行于2018-09-24T20:16:25.794081-07:00 [America/Los_Angeles]

TRACE - doIt running at 2018-09-24T20:16:25.794081-07:00[America/Los_Angeles]

TRACE-可运行于2018-09-25T03:16:25.832025Z. Runnable在2018-09-25T03:16:25.832025Z结束运行.持续时间:PT0.025342S.

TRACE - Runnable starting at 2018-09-25T03:16:25.832025Z. Runnable ending its run at 2018-09-25T03:16:25.832025Z. Duration: PT0.025342S.

TRACE-可运行于2018-09-25T03:18:25.829634Z. Runnable在2018-09-25T03:18:25.829634Z结束运行.持续时间:PT0.001121S.

TRACE - Runnable starting at 2018-09-25T03:18:25.829634Z. Runnable ending its run at 2018-09-25T03:18:25.829634Z. Duration: PT0.001121S.

此屏幕截图中显示的文件.

Files seen in this screenshot.

这篇关于使用Java每2小时生成CSV文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆