import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.*; /**
* 读取动态产生的文件内容
*/
public class RandomAccessRead {
public static Logger logger= LoggerFactory.getLogger(RandomAccessRead.class); //文件默认读取位置为从开始读取
public static final long DEFAULT_START_POSITION=0;
// 读取文件内容输出时采用的编码格式 默认采用ISO-8859-1编码格式,因为RandAccess读取文件内容为该格式
public static final String DEFAULT_OUTPUT_CHARSET="ISO-8859-1";
//读取文件超时时间,默认-1 没有超时时间
public static final long TIMEOUT=-1;
// 相邻两次读取文件内容时间间隔,默认20ms
public static final long DEFAULT_READ_INTERVAL=20; //私有构造方法,防止该对象通过new实例化
private RandomAccessRead(){}; /**
* 动态读取文件内容
* @param inputPath 输入路径
* @param inputFileName 输入文件名称
* @param outputPath 输出路径
* @param endFlag 文件内容中读取结束标志
* @return 文件读取结束位置
*/
public static long read(String inputPath,String inputFileName,String outputPath,String endFlag){
return read(inputPath,inputFileName,outputPath,"",DEFAULT_START_POSITION,DEFAULT_OUTPUT_CHARSET,-1,DEFAULT_READ_INTERVAL,endFlag);
} /**
* 读取动态产生的文件内容 执行输入路径、输入文件名称,输出路径,输出文件名称、读取开始位置,输出时使用的编码格式,超时时间,两次相邻读取文件时间间隔
* @param inputPath 读取文件路径
* @param inputFileName 读取文件名称
* @param outputPath 输出文件路径
* @param outputFileName 输出文件名称 不设置默认为源文件名称
* @param startPosition 文件读取开始位置 不设置默认从文件开始位置读取,其值为0
* @param outputCharset 读取文件内容输出时采用的编码格式 不设置默认采用ISO-8859-1编码格式,因为RandAccess读取文件内容为该格式
* @param timeOut 超时时间 读取的文件长时间没有内容产生,则超时,读取结束,不设置默认没有超时时间
* @param readInterval 相邻两次读取文件内容时间间隔,默认20ms
* @param endFlag 读取文件结束标志
* @return 返回本次读取文件内容的长度,方便下次通过该位置读取文件内容
*/ public static long read(String inputPath,String inputFileName,String outputPath,String outputFileName,long startPosition,String outputCharset,long timeOut,long readInterval,String endFlag) {
//判断路径后面是否带“/” linux下为”\“
inputPath=inputPath.endsWith(File.separator)==true?inputPath:inputPath+File.separator;
String filePath=inputPath+inputFileName;
long endPosition=startPosition;
//判断文件是否存在
RandomAccessFile randomAccess=null;
try {
randomAccess = new RandomAccessFile(filePath, "r");
} catch (FileNotFoundException e) {
logger.error("读取文件:{} 不存在,请检查文件路径", filePath);
e.printStackTrace();
return endPosition;
}
//初始化输出流
outputPath=outputPath.endsWith(File.separator)==true?outputPath:outputPath+filePath;
outputFileName=outputFileName.equals("")==true?inputFileName:outputFileName;
String outputFilePath=outputPath+outputFileName;
if(!new File(outputFilePath).exists()){
try {
new File(outputFilePath).createNewFile();
} catch (IOException e) {
logger.error("输出路径:{}创建失败",outputFilePath);
e.printStackTrace();
return endPosition;
}
}
BufferedWriter bw=null;
try {
bw= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outputFilePath)),outputCharset));
} catch (IOException e) {
e.printStackTrace();
}
long startTime=System.currentTimeMillis();
//上次更新数据时间
long preTime=startTime;
//读取结束标识 读到结束标志
Boolean readEnd=false; try {
String tempStr=null;
StringBuilder sb=null;
while(true) {
randomAccess.seek(startPosition);
sb=new StringBuilder();
while(null!=(tempStr=randomAccess.readLine())){
preTime=System.currentTimeMillis();
//RandomAccessFile读取的文件内容编码为ISO-8859-1,需要转化为指定编码格式
if(!"".equals(outputCharset)){
tempStr=new String(tempStr.getBytes(DEFAULT_OUTPUT_CHARSET),outputCharset);
}
if(!tempStr.contains(endFlag)) {
sb.append(tempStr);
sb.append("\n");
}else{
readEnd=true;
break;
}
//清空tempStr
tempStr=null;
}
//输出到文件中
bw.write(sb.toString());
bw.flush();
//清空sb
sb=null;
endPosition=randomAccess.length();
if(readEnd)
{
break;
}
//判断超时时间
if(timeOut!=-1&&System.currentTimeMillis()-preTime>timeOut) {
logger.info("读取文件超时,读取退出,输入文件路径:{},输出文件路径:{}",filePath,outputFilePath);
break;
}
//读取文件内容间隔时间 -1表示未设置 则使用默认的时间间隔
try {
if(-1==readInterval) {
readInterval=DEFAULT_READ_INTERVAL;
}
Thread.sleep(readInterval);
} catch (InterruptedException e) {
logger.error("线程挂起出现异常,异常信息为:{}",e.getMessage());
e.printStackTrace();
}
//break;
}
} catch (IOException e) {
logger.error("读取文件:{},发生IO异常,异常信息:{}",filePath,e.getMessage());
e.printStackTrace();
}finally {
if(null!=randomAccess)
{
try {
randomAccess.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null!=bw)
{
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
long endTime=System.currentTimeMillis();
logger.info("读取文件时长为:{} ms",(endTime-startTime));
logger.info("文件读取结束,输入文件路径:{},输出文件路径:{}",filePath,outputFilePath);
return endPosition;
}
} public static void main(String[] args) {
//test1();
//test2();
test3();
} /**
* 验证情况1 正常参数
*/
public static void test1(){
String inputPath="F:\\IDE\\DesignPatternWebServer\\src\\main\\java\\com\\main\\etl\\server";
String inputFileName="RandomAccessRead.java";
String outputPath="F:\\";
String outputFileName="test.java";
long startPosition=0;
String outputCharset="UTF-8";
long timeOut=1000;
long readInterval=50;
String endFlag="END";
long endPosition= RandomAccessRead.read(inputPath,inputFileName,outputPath,outputFileName,startPosition,outputCharset,timeOut,readInterval,endFlag);
} /**
* 验证情况2 正常参数 不填输出文件名称
*/
public static void test2(){
String inputPath="F:\\IDE\\DesignPatternWebServer\\src\\main\\java\\com\\main\\etl\\server";
String inputFileName="RandomAccessRead.java";
String outputPath="F:\\";
String outputFileName="";
long startPosition=0;
String outputCharset="UTF-8";
long timeOut=1000;
long readInterval=50;
String endFlag="END";
long endPosition= RandomAccessRead.read(inputPath,inputFileName,outputPath,outputFileName,startPosition,outputCharset,timeOut,readInterval,endFlag);
} /**
* 验证情况3 简化参数形式
*/
public static void test3(){
String inputPath="F:\\IDE\\DesignPatternWebServer\\src\\main\\java\\com\\main\\etl\\server";
String inputFileName="RandomAccessRead.java";
String outputPath="F:\\";
String endFlag="END";
long endPosition= RandomAccessRead.read(inputPath,inputFileName,outputPath,endFlag);
} }
log4j.properties内容如下:
### set log levels ###
log4j.rootLogger = debug,stdout,R,E ### 输出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %p [%t] %c{2} (%M:%L) - %m%n ### 输出etl-web日志到文件 ###
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.ImmediateFlush=true
log4j.appender.R.Append = true
log4j.appender.R.File =F:/logs/etl_web.log
log4j.appender.R.encoding=UTF-8
log4j.appender.R.Threshold = INFO
log4j.appender.R.DatePattern='.'yyyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %p [%t] %c{2} (%M:%L) - %m%n ### 保存异常信息到单独文件 ###
log4j.appender.E = org.apache.log4j.RollingFileAppender
log4j.appender.E.File = F:/logs/etl_error.log
log4j.appender.E.encoding=UTF-8
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %p [%t] %c{2} (%M:%L) - %m%n