QA@IT

DBのテーブルとテキストファイルを比較しテキストファイルにないデーターを出力

6103 PV

はじめての投稿になります。
どうぞ宜しくお願いします。

テキストファイルにある中身とテーブルの値を比較し、一致しなかったものを出力する方法が知りたいです。


○テキストファイル(test.txt)
0001 aaa
0002 bbb

○DBのテーブル(test)
0001 aaa
0002 bbb
0003 ccc

○テキストファイル(result.txt)
(元々は空)

○DBのテーブル(result)
(元々は空)


jsfで作った比較というボタンを押すと同時に、
test.txtの中身とテーブルtestの中身を比較し、
一致しなかったものをresult.txtとテーブルのresultにその一致しなかった
もののデーターを出力するものが作りたいです。
なのでここでは、
result.txtとテーブルのresultに 0003 ccc が出力されるのが正解です。
コードを書いてみたのですが、Daoがnullと出てしまい、上手くいかないのでどなたかアドバイスお願いします。

public List<UserDto> getUserList(Connection connection) throws IOException {

    PreparedStatement prepareStatement = null;
    ResultSet resultSet = null;

    try {

        prepareStatement = connection.prepareStatement(GET_ALL);
        resultSet = prepareStatement.executeQuery();
        List<UserDto> items = new ArrayList<UserDto>();

        String id = null;
        String firstName = null;


        while (resultSet.next()) {

            if (id == null || !id.equals(resultSet.getString(1))) {
                if (id != null) {
                    items.add(new UserDto(id, firstName));

                }
            }
            id = resultSet.getString(1);
            firstName = resultSet.getString(2);


        }
        if (id != null) {
            items.add(new UserDto(id, firstName));
        }
        return items;
    } catch (SQLException e) {
        throw new IOException(e);
    } finally {
        if (resultSet != null) {
            try {
                resultSet.close();

            } catch (SQLException e) {
                logger.warn(e.getMessage(), e);
            }
        }

        if (prepareStatement != null) {
            try {
                prepareStatement.close();
            } catch (SQLException e) {
                logger.warn(e.getMessage(), e);
            }
        }

    }
}

▼ボタンがおされたときの処理

public Compare(String FilePath) throws IOException {

        UserDao userdao = new UserDao();
        UserDtoList = userdao.getUserList(connection);


        File file = new File(C:\test.txt);

        FileReader fr = null; 

        try {
            fr = new FileReader(file.getPath().toString());
        } catch (FileNotFoundException ex) {
        }

        BufferedReader br = new BufferedReader(fr);
        String Read_str = null;

        try {

            while ((Read_str = br.readLine()) != null) {
                boolean isData = false;

                String User_id = Read_str.split(" ")[0];
                String User_firstName = Read_str.split(" ")[1];


                for (UserDto user : UserDtoList)

                    if (user.getId().equals(User_id) {
                        isData = true;

                    }
                }


                if (!isData) {

                    add(connection, User_id, User_firstName);
                    BufferedWriter wStream = new BufferedWriter(new FileWriter(
                            "C:\\result.txt", true));
                    wStream.write(User_id, User_firstName);
                    wStream.newLine();
                    wStream.close();
                }
            }
        } catch (IOException ioe) {

        }
    }





    private void add(Connection connection2, String user_id,
            String user_firstName) throws IOException {
        PreparedStatement prepareStatement = null;
        try {
            prepareStatement = connection.prepareStatement(INSERT_result);
            int fieldNo = 1;
            prepareStatement.setString(fieldNo++, user_id);
            prepareStatement.setString(fieldNo++, user_firstName);

            prepareStatement.executeUpdate();

        } catch (SQLException e) {
            throw new IOException(e);

        } finally {
            if (prepareStatement != null) {
                try {
                    prepareStatement.close();

                } catch (SQLException e) {

                }
            }
        }
    }


    private static final String INSERT_result = "insert into result(id, firstName) values (?,?)";
}

以上です。宜しくお願いします。

  • 何を作っているかとご自分の開発環境ぐらいは書けませんかね? -
  • すみません。横から口を挟ませて下さい。
    addメソッドの外に、SQL文が定義されてますよ。
    あと、addメソッドの修飾子はprivateですが、まさか他のクラスで利用されてませんよね。
    -
  • コードを読めば推測できるはずだから書かなくてもいいとは私は思いません。今回の場合でも質問の最初の 2 行の変わりに、例えば(あくまで例えば)「ASP.NET Web Forms アプリを C# で作ってます。環境は .NET 3.5, Windows Swever 2008, IIS7・・・」というように書いてもらったほうがいいと思うのですが。 -
  • diehardnever さん>
    もし質問者さんの質問に対してコメントされているのでしたら失礼しました。「横から口を挟ませて」と書いてあったので私のコメントに対するものと思いました。
    -
  • SurferOnWwwさん、誤解を招く発言失礼致しました。
    k_lala22さん、addメソッドの外に、SQL文が定義されていてOKでしたね。すみません。
    ただ、addメソッドの修飾子はprivateですが、本当に他のクラスで利用されてたら、Daoがnullになるのかなと思って発言してしまいました。参考にならなかったらすみません。
    -
  • 「Daoがnullと出てしまい」のDaoってUserDaoのことですか?UserDao userdao = new UserDao();が失敗してuserdaoがnullになっているのでしょうか? -
  • >SurferOnWww さま
    失礼しました。環境はwindows8、eclipseでjavaを使っています。
    学校の課題の一環で、上記の通り値を比較してテキストファイルにないものをテキストファイルとデーターベースに出力するというものを作っています。



    -
  • >diehardnever さま
    その部分を念のためpublicでやってみたのですが、相変わらずDaoがnullとでてしまいます...
    なのでDaoのクラスが違うのかなと思うのですが...
    -
  • >blunder3 さま
    List<UserDto> getUserListの部分とUserDaoがnullとでています><
    -
  • blunder3 さんの質問に Yes or No で答えらませんか? そして、答が No なら何がどう違うのか書けませんか? 失礼ながら、何が分からないの分からない、何を質問すればいいのか分からない状態のように見えます。もしそうであればなおさらそうしてもらえないと・・・ -
  • あと、定義不明の変数・メソッドが多々入ったソースをまる投げするのでなく、問題を切り分けして問題の部分のコードだけを過不足なく提示するようにできませんか? 例えば、DB からのデータの取得ができてないのが問題ならその部分のコードのみ提示するとか。 -
  • 大きなお世話かもしれませんが、学校の課題なら学校の先生や聞くのが一番では? 先生なら、生徒と face-to-face で何度もやりとりをして、何が分からないのか何を聞きたいのかを探って回答してもらえるのでは? 掲示板ではそこまで期待はできないですし、質問するにもスキルが要りますし。 -
  • もしかしたらDaoっていうのは、テキストファイルへのアクセスとDBへのアクセスを共通のインターフェースでまとめて統一的に扱えるようにしろってことなんでしょうか?課題に何か前提条件があるのなら、その部分も提示してもらわないと、求められているものが何かよくわからないですね。
    -
  • あとJavaのプログラムではUserDao userdao = new UserDao();が失敗してuserdaoがnullになることは普通は考えにくいので、Daoがnullっていうのはやっぱり腑に落ちないです。たぶん違う意味で言っているのだと思いますが、Daoがnullとは具体的にどういうことかを教えてほしいです。 -
  • @diehardneverさん。僕のコメントはhttp://qa.atmarkit.co.jp/aboutの「コメント機能 - 質問の意図が不明、あるいは肝心な情報が抜けている場合にコメントを残すことで、投稿者に追加情報を催促できます」に従っているつもりで、他意はありません。 -
  • そうですよね。
    blunder3にも、そのようなやり方で僕はeclipseのプロジェクトをインターネットにupすることが出来ました。
    僕の方こそ、勝手にコードを考えてしまってみなさんの意図してる方向でなくてすみません。
    -
  • できれば例外メッセージ、スタックトレース、そのあたりがよくわからないなら「上手くいかない」時、「Daoがnullと出てしまう」時の画面のスクリーンショットなどあると回答しやすくなると思います。 -
  • スクリーンショット掲載するときは、自分が見られてまずいもの(何かのユーザー名やパスワードとか)入らない様に注意してくださいね。 -

回答

t_1221さん、僕が自分で t_1221さんの目指されているものを作ってみました。
参考にしてみて何がわからないか考えてみて下さい。
SurferOnWwwさん、blunder3さんが納得のいくコメントを返してくれる事を期待します。
ここは常識ある方の集まりですので、失礼があったらみんな困ります。
「環境」

Windows7 64bit
jdk1.7.0_75
tomcat7.0.57
servlet-api.jartomcat/libからeclipseへ外部jarで追加
mysql workbench 6.2CE

[DBbean.java]

package beans;

public class DBbean {
    private String id;
    private String firstName;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

[UserDao.java]

package DAO;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import beans.DBbean;
import utils.DaoUtil;
import exception.SQLRuntimeException;

public class UserDao {  
    private final String GET_ALL = "select id,firstName from test order by id"; 
    private DataSource source;
    public UserDao(){
        source = DaoUtil.getSource();
    }   
    public List<DBbean> getUserList(Connection con) throws IOException, SQLException {      
        List<DBbean> items = new ArrayList<DBbean>();
        con = null;
        PreparedStatement pStmt = null;
        ResultSet rs = null;
        try {

            con =source.getConnection();
            pStmt= con.prepareStatement(GET_ALL);
            rs = pStmt.executeQuery();
            DBbean bean = new DBbean();
            while (rs.next()) {
                bean.setId(rs.getString("id"));
                bean.setFirstName(rs.getString("firstName"));
                items.add(bean);
            }       
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        } finally {
            con.close();
            pStmt.close();
            rs.close();
        }
        return items;
    }
}

[TestServlet.java]

package controller;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import utils.DaoUtil;
import beans.DBbean;
import exception.FileNotFoundRuntimeException;
import exception.IORuntimeException;
import exception.SQLRuntimeException;
import DAO.UserDao;

@WebServlet(urlPatterns = { "/JSP/entry" })
public class TestServlet extends HttpServlet{   
    private static final long serialVersionUID = 1L;
    private static final String INSERT_result = "insert into result (id, firstName) values (?,?)";
    private DataSource source;
    public TestServlet(){
        source = DaoUtil.getSource();
    }   
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
        this.doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
        File file = new File("C:\\eclipse\\workspase\\test\\WebContent\\File\\test.file");
        FileReader fr = null; 
        fr = new FileReader(file.getPath().toString());
        BufferedReader br = new BufferedReader(fr);
        Connection con = null;
        try {
            UserDao userdao = new UserDao();
            List<DBbean> UserDaoList = userdao.getUserList(con);
            int i =0;
            String User_id;
            String User_firstName;
            while(br.readLine()!= null){
                i++;
            }
            File out = new File("C:\\eclipse\\workspase\\test\\WebContent\\File\\result.file");
            FileWriter fw = null; 
            fw = new FileWriter(out.getPath().toString());
            BufferedWriter bw = new BufferedWriter(fw);
            for (;i < UserDaoList.size();i++){  
                User_id = UserDaoList.get(i).getId();
                User_firstName =UserDaoList.get(i).getFirstName();          
                add_set(con,User_id, User_firstName);
                bw.write(User_id + " ");
                bw.write(User_firstName);
                bw.newLine();               
            }
            bw.close();
        } catch (FileNotFoundException e) {
            throw new FileNotFoundRuntimeException(e);
        } catch (IOException e) {
            throw new IORuntimeException(e);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        } finally {
            br.close();
        }
    }   
    private void add_set(Connection con,String user_id,String user_firstName) throws SQLException {
        PreparedStatement pStmt = null;
        try {
            con =source.getConnection();
            pStmt = con.prepareStatement(INSERT_result);
            pStmt.setObject(1, user_id);
            pStmt.setObject(2, user_firstName);
            pStmt.executeUpdate();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        } finally {
            con.close();
            pStmt.close();
        }
    }   
}

[index.jsf]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>差分データ書き込み</title>
</head>
<body>
<form action="entry" method="post">
<input type="submit" name="submit" value="比較”/>
</form>
</body>
</html>

[DaoUtil.java]

package utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import exception.SQLRuntimeException;
import utils.SettingUtil;

public class DaoUtil {
public DataSource source;
private static DaoUtil inst = new DaoUtil();
private static final String JDBC_URL = "jdbc.driver.url";
private static final String JDBC_USER = "jdbc.driver.user";
private static final String JDBC_PASS = "jdbc.driver.pass";
private static final String JDBC_DRIVER = "jdbc.driver.classname";
private DaoUtil(){
    source = createDataSource();
}
public static DataSource getSource(){
    return inst.source;
}
private DataSource createDataSource(){
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName(SettingUtil.getProperty(JDBC_DRIVER));   
    bds.setUsername(SettingUtil.getProperty(JDBC_USER));            
    bds.setPassword(SettingUtil.getProperty(JDBC_PASS));                bds.setUrl(SettingUtil.getProperty(JDBC_URL));                      return bds;
}
static {
    try{
        Class.forName(SettingUtil.getProperty(JDBC_DRIVER));
    }catch(ClassNotFoundException e){
        throw new RuntimeException(e);          
    }
}   
public static Connection getConnection(){       
    try{
        Connection connection = DriverManager.getConnection(SettingUtil.getProperty(JDBC_URL),SettingUtil.getProperty(JDBC_USER),SettingUtil.getProperty(JDBC_PASS));
        connection.setAutoCommit(false);    
        return connection;
    }catch(SQLException e){
        throw new SQLRuntimeException(e);   
    }
}
}

[SettingUtil.java]

package utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class SettingUtil {  
    private static SettingUtil inst = new SettingUtil();
    private static final String PRPFNAME = "jdbc.properties";   
    private Properties prop;    
    private SettingUtil(){
        prop = new Properties();
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(PRPFNAME);
        try{
            prop.load(in);
        }catch(IOException iex){
            iex.printStackTrace();
        }
    }

    public static String getProperty(String key){
        return inst.prop.getProperty(key);
    }

}

[jdbc.properties]

jdbc.driver.classname = com.mysql.jdbc.Driver
jdbc.driver.url = jdbc:mysql://localhost/javaservlet?useUnicode=true&amp;characterEncoding=UTF-8
jdbc.driver.user = admin
jdbc.driver.pass = adminpass

[SQL.sql]

create table if not exists javaservlet.test(id varchar(126) primary key,firstName varchar(126)) engine = innodb;
insert into javaservlet.test(id, firstName) values ("0001","aaa");
insert into javaservlet.test(id, firstName) values ("0002","bbb");
insert into javaservlet.test(id, firstName) values ("0003","ccc");
create table if not exists javaservlet.result(id varchar(126) primary key,firstName varchar(126)) engine = innodb;

[web.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">

 <filter>
  <filter-name>SessionFilter</filter-name>
  <filter-class>filter.SessionFilter</filter-class>
</filter>

 <filter-mapping>
  <filter-name>SessionFilter</filter-name>
  <url-pattern>/filter/SessionFilter</url-pattern>
 </filter-mapping>

 <servlet>
  <servlet-name>DBbean</servlet-name>
  <servlet-class>beans.DBbean</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>TestServlet</servlet-name>
  <servlet-class>controller.TestServlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>DaoUtil</servlet-name>
  <servlet-class>utils.DaoUtil</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>UserDao</servlet-name>
  <servlet-class>dao.UserDao</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>SettingUtil</servlet-name>
  <servlet-class>utils.SettingUtil</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>IORuntimeException</servlet-name>
  <servlet-class>exception.IORuntimeException</servlet-class>
 </servlet>
 <servlet>
 <servlet-name>SQLRuntimeException</servlet-name>
  <servlet-class>exception.SQLRuntimeException</servlet-class>
 </servlet>
<servlet>
 <servlet-name>FileNotFoundRuntimeException</servlet-name>
  <servlet-class>exception.FileNotFoundRuntimeException</servlet-class>
 </servlet>

<servlet-mapping>
  <servlet-name>DBbean</servlet-name>
  <url-pattern>/beans/DBbean</url-pattern>
 </servlet-mapping> 
 <servlet-mapping>
  <servlet-name>TestServlet</servlet-name>
  <url-pattern>/controller/TestServlet</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>DaoUtil</servlet-name>
  <url-pattern>/utils/DaoUtil</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>UserDao</servlet-name>
  <url-pattern>/dao/UserDao</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>SettingUtil</servlet-name>
  <url-pattern>/utils/SettingUtil</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>SQLRuntimeException</servlet-name>
  <url-pattern>/exception/SQLRuntimeException</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>IORuntimeException</servlet-name>
  <url-pattern>/exception/IORuntimeException</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>FileNotFoundRuntimeException</servlet-name>
  <url-pattern>/exception/FileNotFoundRuntimeException</url-pattern>
 </servlet-mapping>

 <welcome-file-list>
  <welcome-file>index.jsf</welcome-file>
 </welcome-file-list>

 </web-app>
編集 履歴 (6)
  • @diehardneverさん。このプログラムだとDBのテーブルとテキストファイルの差分をとっているのではなく、テキストファイルの最終行をiとして、DBのテーブルをidでソートした後、i+1以降の行を書き出しているように見えます。違ってたらごめんなさい。これは課題で求めらているものとは、たぶん違う気がします。このコメントは単なる感想です(他意はありません)。 -
  • すみません、至急見直します。
    暫しお待ちください。blunder3さん。
    -
  • @diehardneverさん。ちなみにt_1221さんのプログラムではテキストファイルを1行読むたびにDBのテーブルのメモリ内コピーを全件検索して、idが一致しなかったら出力しているように見えます。それだとDBのテーブル側だけに存在するidを持つ行は出力されない気がします。例えば「0003 ccc」は出力されないのではと。でも質問の趣旨はそれじゃなさそうなんで回答は保留かと。 -
  • @diehardneverさん。すみません。コメントが入れ違いになっていました。別にコードを修正しろという意図で言っていないので、どちらでも構いませんよ。 -
  • @blunder3さんのおっしゃるとうり、DBのテーブルをidでソートした後、i+1以降の行を書き出しているだけでした。考えが足りませんでした。申し訳ありません。 -
  • そこで解決策なんですが、test.txtのデータを一旦DBのtestfileという新規のテーブルに格納して、次のSQL文を発行して一致しなかったものを出力するという手法はどうでしょう。
    select * from testfile left outer join text on (testfile.id= text.id) where text.id is null ;
    -
  • ↑のSQL文修正します。
    select * from testfile left outer join test on (testfile.id= test.id) where test.id is null ;
    -
  • 勿論、javaのクラス上でtest.txtとDBのtestテーブルを比較する方法もあるでしょう。でも、それを僕が考え出して回答しても、このサイトの趣旨に反すると思いますので、@t_1221さんが考え出してくれる事を期待しますし、コメントも投稿したいと思います。 -
  • 上のSQL文だと、testfileだけに存在してtestに存在しないものは出力されますが、testだけに存在してtestfileに存在しないものは出力されないですよね。つまり「0003 ccc」は出力されないと思いますけど。 -
  • select * from testfile where not exists(select * from test where testfile.id=test.id) union select * from test where not exists(select * from testfile where testfile.id=test.id); -
  • @blunder3さん、未熟者ですみません。
    ↑ のSQL文は検証済です。ご高覧下さい。
    -
  • 確認しましたが、問題ありませんでした。修正ありがとうございます。
    -

付け加えるのを忘れていたのですが、GET_ALLのSQLは以下になります><

private static final String GET_ALL = "select id,firstName from test order by id";

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。