Java 重构文本文件分析分批完成

Java 重构文本文件分析分批完成,java,refactoring,Java,Refactoring,我有三个单独的文件解析函数,它们将文本文件转换为对象,然后将这些值插入sqlite数据库。除了对象类之外,它们基本上是相同的 过程如下: 使用http下载文件 计算进度计算文件中的行数 删除目标表中以前的所有记录 使用BufferedReader打开文件 一次读取2000行并将其转换为对象 在事务中将2000条记录插入sqlite 循环直到完成 我不知道如何使这段代码通用,以允许使用任何类来创建对象,然后决定使用哪个DAL函数来持久化数据。Java不是我的第一语言,所以任何指导都很好 以下是我正

我有三个单独的文件解析函数,它们将文本文件转换为对象,然后将这些值插入sqlite数据库。除了对象类之外,它们基本上是相同的

过程如下:

  • 使用http下载文件
  • 计算进度计算文件中的行数
  • 删除目标表中以前的所有记录
  • 使用BufferedReader打开文件
  • 一次读取2000行并将其转换为对象
  • 在事务中将2000条记录插入sqlite
  • 循环直到完成
  • 我不知道如何使这段代码通用,以允许使用任何类来创建对象,然后决定使用哪个DAL函数来持久化数据。Java不是我的第一语言,所以任何指导都很好

    以下是我正在使用的代码:

    public void downloadPendingPoleInspections() {
    
        int count;
        String filePath;
        Inspections inspections = Inspections.getInstance();
    
        filePath = Environment.getExternalStorageDirectory() + File.separator + "inspections.txt";
    
        try {
    
            downloadFile("http://localhost/api/inspectionservices.aspx?o=retrieve", "pendinginspections.txt", POST_PENDING_INSPECTIONS_PROGRESS_UPDATE);
    
            int totalInspections = getLineCount(filePath);
    
            inspections.deleteAllPendingInspections();          
    
            File file = new File(filePath);
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
    
            int i = 0;
            int j = 0;
    
            List<PendingInspection> batch = new ArrayList<PendingInspection>();
    
            while ((line = br.readLine()) != null) {
                String[] values = line.split(" ");
    
                PendingInspection pending = new PendingInspection(
                        Integer.parseInt(values[0]), values[1],
                        Double.parseDouble(values[2]),
                        Double.parseDouble(values[3]));
    
                batch.add(pending);
                i++;
                j++;
    
                if (i >= 2000) {
    
                    inspections.pendingInspectionsBatchInsert(batch);                   
                    batch.clear();
                    i = 0;                  
                }
            }
    
            if (i > 0) {
                inspections.pendingInspectionsBatchInsert(batch);
                batch.clear();
            }
    
            br.close();
            file.delete();
    
        } catch (Exception e) {
            Log.e("SyncActivity", e.toString());            
        }       
    }
    
    剪断。。。。getter和setter实现

    public class PInspection implements Inspectable{
        private int id;
        private String number;
        private double x;
        private double y;
    
    public PInspection(int id, String poleNumber, double x, double y) {
        this.id = id;
        this.number = number ;
        this.x = x;
        this.y = y;
    }
    
    除了对象类之外,它们基本上是相同的

    听起来您希望为作为批处理过程一部分创建的所有这些对象提供一个公共接口。我建议如下:

    public interface Batchable  {  void doBatch();  }
    
    然后执行以下操作:

    public class Foo implements Batchable  {}  
    public class Bar implements Batchable {}
    

    现在,您可以让每个类为
    doBatch
    实现自己的函数体,并且您至少部分地抽象出了了解该类的需要。现在,就一次保存2000条记录而言,为什么不在一个大型事务中同时推送它们呢。如果不这样做,您将面临数据完整性损失的风险。

    我将其拆分为一个抽象基类和一些实现。基类可能如下所示:

    public abstract class Downloader {
        protected abstract void processLine(String[] line);
        protected abstract void save();
        protected abstract String file();
    public void downloadPendingPoleInspections() {
    
        int count;
        String filePath;
    
        filePath = Environment.getExternalStorageDirectory() + File.separator + file();
    
        try {
    
            downloadFile("http://localhost/api/inspectionservices.aspx?o=retrieve", "pending" + file(), POST_PENDING_INSPECTIONS_PROGRESS_UPDATE);
    
            int totalInspections = getLineCount(filePath);
    
            File file = new File(filePath);
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
    
            int i = 0;
            int j = 0;
    
    
            while ((line = br.readLine()) != null) {
                processLine(line.split(" "));
                i++;
                j++;
    
                if (i >= 2000) {
                    save()
                    i = 0;                  
                }
            }
    
            if (i > 0) {
                save()
            }
    
            br.close();
            file.delete();
    
        } catch (Exception e) {
            Log.e("SyncActivity", e.toString());            
        }       
    }
    
    public class InspectionDownloader extends DownLoader {
        Inspections inspections = Inspections.getInstance();
        List<PendingInspection> batch = new ArrayList<PendingInspection>();
    
        public InspectionDownloader() {
            inspections.deleteAllPendingInspections();
        }
    
        protected void processLine(String[] values) {
            PendingInspection pending = new PendingInspection(
                Integer.parseInt(values[0]), values[1],
                Double.parseDouble(values[2]),
                Double.parseDouble(values[3]));
            batch.add(pending);
        }
    
        protected void save() {
            inspections.pendingInspectionsBatchInsert(batch);
            batch.clear();
        }
        protected String file() { 
            return "inspections.txt";
        }
    }
    
    对于要处理的每种类型,您都可以创建一个小实现,如下所示:

    public abstract class Downloader {
        protected abstract void processLine(String[] line);
        protected abstract void save();
        protected abstract String file();
    public void downloadPendingPoleInspections() {
    
        int count;
        String filePath;
    
        filePath = Environment.getExternalStorageDirectory() + File.separator + file();
    
        try {
    
            downloadFile("http://localhost/api/inspectionservices.aspx?o=retrieve", "pending" + file(), POST_PENDING_INSPECTIONS_PROGRESS_UPDATE);
    
            int totalInspections = getLineCount(filePath);
    
            File file = new File(filePath);
            BufferedReader br = new BufferedReader(new FileReader(file));
            String line;
    
            int i = 0;
            int j = 0;
    
    
            while ((line = br.readLine()) != null) {
                processLine(line.split(" "));
                i++;
                j++;
    
                if (i >= 2000) {
                    save()
                    i = 0;                  
                }
            }
    
            if (i > 0) {
                save()
            }
    
            br.close();
            file.delete();
    
        } catch (Exception e) {
            Log.e("SyncActivity", e.toString());            
        }       
    }
    
    public class InspectionDownloader extends DownLoader {
        Inspections inspections = Inspections.getInstance();
        List<PendingInspection> batch = new ArrayList<PendingInspection>();
    
        public InspectionDownloader() {
            inspections.deleteAllPendingInspections();
        }
    
        protected void processLine(String[] values) {
            PendingInspection pending = new PendingInspection(
                Integer.parseInt(values[0]), values[1],
                Double.parseDouble(values[2]),
                Double.parseDouble(values[3]));
            batch.add(pending);
        }
    
        protected void save() {
            inspections.pendingInspectionsBatchInsert(batch);
            batch.clear();
        }
        protected String file() { 
            return "inspections.txt";
        }
    }
    
    公共类检查DownLoader扩展了DownLoader{
    检查=检查。getInstance();
    列表批处理=新建ArrayList();
    公共检查下载程序(){
    检查。删除所有未决检查();
    }
    受保护的void processLine(字符串[]值){
    PendingInspection pending=新的PendingInspection(
    整数.parseInt(值[0]),值[1],
    Double.parseDouble(值[2]),
    Double.parseDouble(值[3]);
    批量添加(待定);
    }
    受保护的无效保存(){
    检验。挂起检验批插入(批);
    batch.clear();
    }
    受保护的字符串文件(){
    返回“inspections.txt”;
    }
    }
    

    通过这种方式,可以将可重用逻辑集中在基类中,并将特殊逻辑转移到小型的、有重点的专用类中。此模式称为模板化方法。您可以看到,派生类非常关注它所负责的类型的特殊操作。

    这些类已经实现了一个公共接口,但这并不能真正解决问题,因为每个类都有不同数量的属性要从文件中解析。2000记录批处理之所以完成,是因为它在android平板电脑上运行,我可以导入超过10万条记录,而且由于潜在提交时间较长,我需要显示进度。数据/类的结构是什么?请把这个加到你的原件上post@eptiliom进一步一次做2000并不能给你带来任何好处。也许再问一个问题会更好,但在提交大量记录时,你会如何显示进步,除了把它分成小块并在完成后报告外?@eptiliom这样做很好。您知道正在处理的数组的大小。您只需要一个函数,它以“随机”的间隔轮询并返回已迭代的当前百分比。快速而肮脏的方法是跟踪当前索引,让函数返回
    (double)index/arraySize
    ,这样您就可以简单地将其称为:InspectionDownloader d=new InspectionDownloader();基类downloadPendingPoleInspections方法将负责实际工作吗?