问题:IO输出多个字段,取的三张表的字段也不一样,1.如何在输出的文件表中添加String类型的相应组长的字段???要求要和表1、表2、表3的字段相对应!!!
2.如何先先输出第一行标题,然后再循环输出表的内容??3.如何添加一列字段计算合计:(业务量*单价)??4.怎样将null值显示为没有值??输出为:
组长  业务量  单价  员工编号  经理  地区   合计
组长1  A       B       C     null   null   A*B
....   ..     ...      ...   ...    ...    ...
组长2  D       E       F     null    G     D*E
....  ...     ..       ..    ...    ...    ...
组长3  H       I       J      K     null   H*I
....  ..      ..      ...    ...    ...    ...
import java.sql.*;
import java.util.*;
import java.io.*;public class test extends ClassObj{
public static void main(String[] args) throws Exception {
        try {
            ArrayList<ClassObj> lst = test.getResultLst();
            String contents = test.formatLst(lst);
            String fileName = "C:\\result.txt";
            test.saveFile(fileName, contents);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  static ArrayList<ClassObj> getResultLst() throws Exception {
        String url = "jdbc:odbc:study";
        String user = "sa";
        String password = "123";
ArrayList <ClassObj> lst = new ArrayList <ClassObj>();
        Connection con = null;
        Connection con2 = null;
        Connection con3 = null;
        PreparedStatement pstmt = null;
        
        ResultSet rs = null;
        ResultSet rs2 = null;
        ResultSet rs3 = null;
        String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
        String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G from 表2";
        String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K from 表3";
        try{
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            con = DriverManager.getConnection(url,user,password);            pstmt = con.prepareStatement(sql);
            pstmt2 = con.prepareStatement(sql2);
            pstmt3 = con.prepareStatement(sql3);
            rs = pstmt.executeQuery();
            rs2 = pstmt2.executeQuery();
            rs3 = pstmt3.executeQuery();
          String fa = "组长1";
          String fb = "组长2";
          String fc = "组长3";
          
          ClassObj c1=null;
          while(rs.next()){               //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
              c1=new ClassObj();            //c1.setBand(rs.getString("fa"));?????
              c1.setBuss(rs.getDouble("A"));
              c1.setPrice(rs.getDouble("B"));
              c1.setId(rs.getString("C"));
                                             //怎么才能计算合并输出????
                                            //c1.setId(rs.getDouble(A*B));
              lst.add(c1);
          }
          while(rs2.next()){
              c1=new ClassObj();
              c1.setBuss(rs.getDouble("D"));
              c1.setPrice(rs.getDouble("E"));
              c1.setId(rs.getString("F"));
              c1.setLand(rs.getString("G"));
              lst.add(c1);
          }
          while(rs3.next()){
              c1=new ClassObj();
              c1.setBuss(rs.getDouble("H"));
              c1.setPrice(rs.getDouble("I"));
              c1.setId(rs.getString("J"));
              c1.setMan(rs.getString("K"));
              lst.add(c1);
          }        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if (rs != null)
                    rs.close();
                if (pstmt != null)
                    pstmt.close(); 
                if (con != null)
                    con.close();
                
            }catch(Exception e){}
        }
      }
static void saveFile(String fileName, String contents) 
throws IOException { 
File f = new File(fileName); if (f.exists()){ 
throw new IOException("file exists..."); 

if (!f.createNewFile()) { 
throw new IOException("file create failure..."); 
} try { 
BufferedWriter output = new BufferedWriter(new FileWriter(f)); 
output.write(contents); 
output.close(); 
} catch (Exception e) { 
throw new IOException(e); 

} static String formatLst(ArrayList <ClassObj> lst){ 
String contents = "";                   //如何在这先循环第一行标题??
for(int i=0;i <lst.size();i++){ 
contents +=lst.get(i).getBand+"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n"; 

return contents; 

}
class ClassObj {
    private String Band;    private Double Buss;    private Double Price;
    
    private String Id;
    
    private String Land;
    
    private String Man;
   
    private Double Sum;
    
//get..set
    public String toString() {
        return "ClassObj{classBand=" + this.classBand +",classId="
                + this.classId + ",classGroup="
                + this.classGroup + ",classSum="
                + this.classSum + ",classNo=" + this.classNo +"}";
    }
}

解决方案 »

  1.   

    1.如何在输出的文件表中添加String类型的相应组长的字段???要求要和表1、表2、表3的字段相对应!!! 这句话怎么都看不懂楼主解释一下
      

  2.   

    3.如何添加一列字段计算合计:(业务量*单价)??
    合计是前2个字段的乘积,可以在遍历结果集时放到对象的sum字段中,也可以在显示时用2个字段的乘积表示static String formatLst(ArrayList <ClassObj> lst){ 
    //2.如何先先输出第一行标题,然后再循环输出表的内容??
    //2.标题是固定的,不能写死吗?
    String contents = "组长  业务量  单价  员工编号  经理  地区  合计 "; //如何在这先循环第一行标题??
    String band = "";
    String ……
    for(int i=0;i <lst.size();i++){
    4.怎样将null值显示为没有值??输出为:
    band = lst.get(i).getBand() == null ? "" :  lst.get(i).getBand();
    ……
    contents += band +"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n"; 

    return contents; 

    }
      

  3.   

    楼主,你怎么还在做这个啊,嘿嘿。
    这里指出几个疑点,不对的话请高手指正了。
    1.代码中
    pstmt = con.prepareStatement(sql);
                pstmt2 = con.prepareStatement(sql2);
                pstmt3 = con.prepareStatement(sql3);
                rs = pstmt.executeQuery();
                rs2 = pstmt2.executeQuery();
                rs3 = pstmt3.executeQuery();
    但是
    finally{
                try{
                    if (rs != null)
                        rs.close();
                    if (pstmt != null)
                        pstmt.close(); 
                    if (con != null)
                        con.close();
                    
                }catch(Exception e){}
            }虽然最后con关了,但我觉得好习惯还是rs和stmt2.你开3个sql来查,其实一个sql就可以搞定你要的那个表格形式了。3.btw:6楼,他的sql的表头可能会随时加上另外的一列,所以代码里面估计他不能写死。
    可以先
    String title = "";
    if(lst!=null&&lst.size()>0){
       title = lst.get(0).get***+*****+\n;
    }
    下面的for从i=1开始计算,当然要判断lst.size()>1。
      

  4.   

    因为代码太长了所以finally统一出口就简写了!
    我先试试大家给出的主意!
      

  5.   

    第一个问题的意思是,我开三个sql的目的是,分别在三组数据集中再跟着跑一个String类型的字段,例如:组长在SQL中是没有的,我先声明组长的名字String fa = "组长:张三";String fa = "组长:李四";String fa = "组长:王五";然后在while里分别跟着三张相应的表跑,while(rs.next()){   //怎样将fa,跟相应的rs一起循环输出。
               c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????这儿应该有个for循环!
                  c1.setBuss(rs.getDouble("A"));
                  c1.setPrice(rs.getDouble("B"));
                  c1.setId(rs.getString("C"));
           //请问如何在遍历结果集时放到对象的sum字段中????能讲的详细点吗??
                              //c1.setId(rs.getDouble(A*B));????
                  lst.add(c1);
              }
    六楼的朋友写的输出标题的方法和解决null方法看明白了,七楼的朋友“不能写死”的代码没有看明白,能给写的再具体点吗??
      

  6.   


    1.如果你每一行都要加上组长:张三的话,那你就在ClassObj里面再加个属性标识组长,然后在rs的每个while里面分别set进去。输出的时候再get出来。比如 while(rs.next()){               //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
                  c1=new ClassObj();            //c1.setBand(rs.getString("fa"));?????
                 c1.setCaptain("组长:张三"); //第一个结果集的组长
                  c1.setBuss(rs.getDouble("A"));
                  c1.setPrice(rs.getDouble("B"));
                  c1.setId(rs.getString("C"));
                                                 //怎么才能计算合并输出????
                                                //c1.setId(rs.getDouble(A*B));
                  lst.add(c1);
              }
              while(rs2.next()){
                  c1=new ClassObj();
      c1.setCaptain("组长:李四"); //第二个结果集的组长
                  c1.setBuss(rs.getDouble("D"));
                  c1.setPrice(rs.getDouble("E"));
                  c1.setId(rs.getString("F"));
                  c1.setLand(rs.getString("G"));
                  lst.add(c1);
              }
              while(rs3.next()){
                  c1=new ClassObj();
     c1.setCaptain("组长:王五"); //第三个结果集的组长
                  c1.setBuss(rs.getDouble("H"));
                  c1.setPrice(rs.getDouble("I"));
                  c1.setId(rs.getString("J"));
                  c1.setMan(rs.getString("K"));
                  lst.add(c1);
              }
    2.合计的问题不知道你解决了没有,可以修改sql
            String sql = "select 业务量 as A,单价 as B,员工编号 as C,NVL(业务量,0)*NVL(单价,0) as HJ from 表1";
            String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G,NVL(业务量,0)*NVL(单价,0) as HJ  from 表2";
            String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K,NVL(业务量,0)*NVL(单价,0) as HJ  from 表3";
    然后,在你的while中,同样可以get到 HJ这列,然后set到ClassObj中去。
    或者,你的  //怎么才能计算合并输出????
                                                //c1.setId(rs.getDouble(A*B));
    用 c1.set合计 (rs.getDouble("A")*rs.getDouble("B")); //double的乘法是不是这样我忘了,不好意思。
    3.你的表头,如果是在每个结果集的最先都要加,那你参照办法1,在每个while(rs.next())的前面,new一个ClassObj,把表头set进去,再把这个ClassObj添加到你的列表里面。ArrayList是顺序的,所以不会乱。
    如果只要第一行加,那就只在第一个while(rs.next())的前面,new一个ClassObj,把表头set进去。
      

  7.   

    c0=new ClassObj();
    c0.setCaptain("组长");
    c0.setBuss("业务量");
    c0.setPrice("单价");
    c0.setId("员工编号");
    c0.setLand("地区");
    c0.setMan("经理");
    lst.add(c0);
    while(rs.next()){
    ......
    }
    表头是这么写吗??
    还想问个问题如果第一天跑了50条记录,第二天我想紧跟着从第51条开始跑第二天的记录怎样才能实现这个需求???
      

  8.   


    对就这么加。不知道你的表里面有没有日期,如果有日期就好办。你在where条件里面加上 
    where to_char(日期字段,'YYYYMMDD') = to_char(sysdate,'YYYYMMDD')
    就可以只查当天的记录。
    sysdate 是系统日期。
    系统日期可以通过数字来调整。比如,你要查当天的前一天,你就把上面的where的sysdate改成sysdate-1.
    你还可以通过系统日期来精确到秒。比如,你要查当天的8点30分30秒之前的,就可以用
    where to_char(日期字段,'YYYYMMDDHH24MISS') < to_char(sysdate,'YYYYMMDD')||'083030'
      

  9.   

    您误会我的意思了,我是希望做一个判断如果文件中已经有(表头1条)+5条数据的话,就从第(表头1条)+6条开始跑新的数据。我的思路先是解决if (f.exists())和if (!f.createNewFile())对已经存在的文件的异常处理,然后判断文件中已经有的数据,再跟着已经有的数据后面循环跑,
                      表头
                 第1条。。
                 第2条。。
                 第3条。。
                 第4条。。
                 第5条。。
    新的数据--》 第6条。。
                 。。
    还有一个问题,要是想运行一次查2个SQL并且分别输出到两个txt文件,需要在代码里改哪些地方??
      

  10.   

    关于计算合计的问题,我用的是MS的SQL Server,NVL显示为不可识别的函数。另外c1.set合计 (rs.getDouble("A")*rs.getDouble("B"));运行时报错,我考虑是不是应该写个方法把值传进去??
      c1.set合计 (getSum(rs.getDouble(A),rs.getDouble(B)));
      .....
     static double getSum(Double A,Double B){ 
     return A*B;
    }
    合计的问题还是没解决,还要麻烦大家跟想想办法。
      

  11.   


    文件追加,只要把saveFile改一下,见注释: static void saveFile(String fileName, String contents) throws IOException {
    File f = new File(fileName);
    BufferedWriter output = null;
    try {
    //如果不存在
    if (!f.exists()) {
    //建新文件
    if (!f.createNewFile()) {
    throw new IOException("file create failure...");
    }
    }
    //这里的 true表示文件追加,false表示原来的都不要
    output = new BufferedWriter(new FileWriter(f, true));
    output.write(contents); } catch (Exception e) {
    e.printStackTrace();
    } finally {
    //最后在finally关闭
    try {
    output.close(); } catch (Exception e) { }
    }
    } 还有一个问题,要是想运行一次查2个SQL并且分别输出到两个txt文件,需要在代码里改哪些地方??
    那就调两次saveFile,你要存到两个文件里面的分别用不同的ArrayList。或者你存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。
      

  12.   


    你用SQL Server噢,NVL是oracle的,我上次以为你用oracle~~~.NVL(param1,param2)的意思是:如果param1为NULL,则输出param2.你看看SQLSERVER里面有没有类似的函数。
    (rs.getDouble("A")*rs.getDouble("B"));运行时报错。我上次写的时候忘了rs.getDouble("B")是得到一个Double对象,而不是一个double值,用
    rs.getDouble("A").doubleValue()*rs.getDouble("B").doubleValue() 就可以了,不过要求你数据库输出的必须是double或整数。
    或者也可以
    static double getSum(Double A, Double B) {
    return A.doubleValue() * B.doubleValue();
    }
      

  13.   

    暈,你跟著跑什麼啊跑。
    兩個解決方案:
    一、編寫SQL搞定,比如用聚合函數等。 
    二、定義javabean ,把你所要用到的元素都包含進去。如果有要計算的字段,比如(業務金額 字段中,就可以在其 get()方法中寫入:業務量*單價。等等。
    再用List<javabean> 去裝數據。 你就資料庫中抓出來往裡面扔吧,有多少扔多少,想怎麼扔就怎麼扔。
      

  14.   

    关于运行一次查2个SQL并且分别输出到两个txt文件的问题:
    1.调两次saveFile,你要存到两个文件里面的分别用不同的ArrayList,这个方法搞明白了!十分感谢。
    2.存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。这种方法不太明白,能具体写下代码吗??
    关于合计如果当数据库表中的相应字段类型不是Double,而是String或Float或int类型时,分别应当如何转换类型???
      

  15.   

    还有个问题能帮忙编写一个*.bat文件,能够依次运行以下步骤。 
    1.运行cmd。2.进入C盘根目录。3.执行javac test.java命令。4.执行java test命令。 
    并能够保持在cmd窗口显示执行java test之后的内容。
      

  16.   


     2.存完第一个之后,将ArrayList清空,再查第二个sql的结果放到第一个里面去。这种方法不太明白,能具体写下代码吗??
    简单写下:
    ArrayList<..> lst = new ArrayList<..>();
    ...
    rs = execute sql 
    while(rs.next){
     ...
     lst.add(...)
    }
    ...
    saveFile(..);lst = new  ArrayList<..>();
    再来一次~~~ 关于合计如果当数据库表中的相应字段类型不是Double,而是String或Float或int类型时,分别应当如何转换类型???
    这个String要看你数据库里面有没有小数点,有的话用rs.getString(...)后用Double转换,然后就可以跟Double一样。没小数点,就用Integer.parserInt(String s)转成Integer,然后再Integer.intValue去乘。int的直接rs.getInt直接乘。Float的不晓得,没用过这么高级的。
    这些其实你都可以google或百度得到的。
      

  17.   


    你是想写完程序点下这个文件就看结果?搞这么麻烦还不如直接在IDE里面 run as java bean或run as java application 来得快。
    如果你做完了要写.bat文件,那倒是另一回事。
    cd D://你class放得路径TOOLBAR
    java -classpath "./lib/jdom.jar;./lib/log4j-1.2.15.jar" com.socix.financial.AppLauncher
    -classpath的值"./lib/jdom.jar;./lib/log4j-1.2.15.jar"指名你用到的所有jar的路径,com.socix.financial.AppLauncher就是你那个有main方法的类名。
      

  18.   

    1、msSQL中日期的字段是:“2009-12-02 12:00:00.000”的格式我想只取“2009-12-02”这个部分,用left(日期,10)取出来的显示效果不对,有别的更合适的函数吗??
    2、日期还是上面的格式,我想同时取2009-11-02,2009-11-10至2009-11-15,2009-11-17至2009-11-19这三个时间段的数据where应该怎么写时间范围?
      

  19.   

    1:convert(char(10),getDate(),120)
    2:between...and...
      

  20.   


                while (rs.next()) {
                    c1 = new ClassObj();
                    c1.setClassId(rs.getString("A"));
                    c1.setClassGroup(rs.getString("B"));
                    c1.setClassNo(rs.getString("C"));
                    lst.add(c1);
                }
                .....
        static String format(ArrayList<ClassObj> lst) {
            String contents = "";
            String Gg = "组长";          for (int i = 0; i < lst1.size(); i++) {    
            String sa=lst.get(i).getClassId();         //要在这一层将String类型A、B转换成int类型相乘并循环输出,这一段代码应该怎么写??
            String sb=lst.get(i).getClassGroup();//??
            int Gd =(Integer.parserInt(String (sa))).intValue*(Integer.parserInt(String (sb))).intValue;//?????
            contents += Gg+"\t"+lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()+"\t"+ Gd +"\n";
            }
            return contents;
        }
    数据类型这块知识还有些模糊,麻烦帮忙给写写代码。
      

  21.   

    1.convert(varchar(10),date_col,121))='2009-12-02';2.select * from tbl where  (convert(varchar(10),date_col,121))='2009-12-02' or convert(varchar(10),date_col,121)) between '2009-11-10' and '2009-11-15' or
    convert(varchar(10),date_col,121)) between '2009-11-17' and '2009-11-19' )
      

  22.   

     for (int i = 0; i < lst1.size(); i++) {    
            String total = "";
            String sa=lst.get(i).getClassId();         //要在这一层将String类型A、B转换成int类型相乘并循环输出,这一段代码应该怎么写??
            String sb=lst.get(i).getClassGroup();//??
            try{
                   //可以转换为int的乘起来再变成string
    total = String.valueOf(Integer.parseInt(sa)*Integer.parseInt(sb));
    }catch(Exception e){
                  //不可以转换的例如字母字符、null等等,让总计变零
    total = "0";
    }
    System.out.println(total);
            //int Gd =(Integer.parserInt(String (sa))).intValue*(Integer.parserInt(String (sb))).intValue;//?????
            contents += Gg+"\t"+lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()+"\t"+ total +"\n";
            }
      

  23.   

       String sql = "select convert(char(10),wdate,120) as A,单价 as B,员工编号 as C from 表1";
            。
              while(rs2.next()){
                  c1=new ClassObj();
       c1.setBuss(rs.getString("A"));  //运行时报错,convert()是什么类型的,为什么用String取不出来?
                  c1.setPrice(rs.getString("B"));
                  c1.setId(rs.getString("C"));
                  lst.add(c1);
              }
      

  24.   

    你是不是mysql啦?这个是mysql的日期转换函数
    convert(char(10),wdate,120) 改为121
    这个意思好像就是把你的wdate转为"yyyy-mm-dd"的字符串。
    说实话,mysql我没用过。你baidu或者google一把 mysql 日期转换函数,应该一堆出来的。我也是查的。
      

  25.   

    http://hi.baidu.com/suyuan19/blog/item/6660b435ae86bf89a61e12b9.html
      

  26.   

    SQL Server里显示的很正常,但是程序里rs.getString("A")就报错,不知道是不是类型有问题?
      

  27.   

    楼主看看我给你的那个链接我以为是mysql
      

  28.   

    不好意思这里是因为SQL输出的顺序有问题,我已经解决了!
      

  29.   

    请问要是输出文件生成后,再将其逐行insert写入到SQL server的表中,后面的代码应该怎么写??
      

  30.   


    两个选择:
    1.调用saveFile之后,再for循环lst一把,然后把lst里面的数据一条条的insert回去。
    2.如果不是实时的,就是说,你今天生成文件,明天写回去,那么你就读文件,读一行insert一行或者整个文件都读完再一起for循环写回去。。
      

  31.   

    自己建下表噢,我这里的表结构是完全照你提供的代码里面文本文件的格式来的,请根据实际情况对insert语句进行调整/**
     * 逐行文件写回数据库,可以把里面的if (c.length == 7) {}包含的这段独立拿出来作为一个方法,我懒得改了。
     * 
     * @param fileName
     *            文件名
     * @param con
     *            jdbc连接对象,在外部连上后传入。外部调用的函数要记得关闭。
     * @throws Exception
     */
    public static void readFileWriteBack(String fileName, Connection con)
    throws Exception {
    String s = "";
    File f = new File(fileName);
    if (!f.exists()) {
    throw new Exception("file doesn't exist....");
    }
    BufferedReader br = null;
    PreparedStatement pstmt = null;
    try {
    br = new BufferedReader(new InputStreamReader(
    new FileInputStream(f))); while ((s = br.readLine()) != null) {
    // 如果这行有合计,表示是属于表头,忽略掉这行
    if (s.indexOf("合计") > 0) {
    continue;
    }
    // 将这行拆分开,按你已有格式:组长 业务量 单价 员工编号 经理 地区 合计
    String[] c = s.split("\t");
    printArray(c);// 打印看看数据对不对,这行可去掉
    // 只有这行拆出来是7个数据才写入数据库,对应你的文件,你写了几个,这里改成几
    if (c.length == 7) {
    // tbl_report是要写回的数据表,最好
    String sql = "insert into tbl_report(组长,业务量,单价,员工编号,经理,地区,合计)"
    + "values(?,?,?,?,?,?,?)";
    pstmt = con.prepareStatement(sql);
    // 第一个参数代表sql中的第几个问号,第二个参数代表从文件中取出的每行数据的
    // 转换成数组后的值。
    pstmt.setString(1, c[0]);
    pstmt.setString(2, c[1]);
    // 单价这行不知道你数据类型,如果int就用setInt,如果小数,可用setBigDecimal(new
    // BigDecimal(c[2]));其他数字类型同理。
    pstmt.setString(3, c[2]);
    pstmt.setString(4, c[3]);
    pstmt.setString(5, c[4]);
    pstmt.setString(6, c[5]);
    pstmt.setString(7, c[6]);
    pstmt.execute();
    }
    } System.out.println("file write back finished");
    } catch (Exception e) {
    throw e;
    } finally {
    try {
    if (pstmt != null) {
    pstmt.close();
    }
    br.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    } /**
     * savaFile后,ArrayList数据写回数据库,可以把里面的if (!man.equals("经理")) {}包含的这段调用
     * 我在readFileWriteBack这里说的,如果你独立把它拿出来了的话。
     * 
     * @param lst
     *            savaFile完了之后的ArrayList
     * @param con
     *            jdbc连接对象,在外部连上后传入。外部调用的函数要记得关闭。
     * @throws Exception
     */
    public static void readListWriteBack(ArrayList<ClassObj> lst, Connection con)
    throws Exception {
    PreparedStatement pstmt = null;
    try { for (int i = 0; i < lst.size(); i++) {
    ClassObj co = lst.get(i);
    // 如果这行有经理,表示是属于表头,忽略掉这行,(可以跟上面一样采用合计,
    // 我这里不知道你合计的属性是什么
    String man = co.getMan();
    if (!man.equals("经理")) {
    // tbl_report是要写回的数据表,最好
    String sql = "insert into tbl_report(组长,业务量,单价,员工编号,经理,地区,合计)"
    + "values(?,?,?,?,?,?,?)";
    pstmt = con.prepareStatement(sql);
    // 第一个参数代表sql中的第几个问号,第二个参数代表从ClassObj中取出的每个数据
    // co的属性,与insert的问号一一对应。请自己修改。
    pstmt.setString(1, co.getClassGroup());
    pstmt.setString(2, co.getClassGroup());
    // 单价这行不知道你数据类型,如果int就用setInt,如果小数,可用setBigDecimal(new
    // BigDecimal(co.getClassGroup()));其他数字类型同理。
    pstmt.setString(3, co.getClassGroup());
    pstmt.setString(4, co.getClassGroup());
    pstmt.setString(5, co.getClassGroup());
    pstmt.setString(6, co.getClassGroup());
    pstmt.setString(7, co.getClassGroup());
    pstmt.execute();
    }
    } System.out.println("arraylist write back finished");
    } catch (Exception e) {
    throw e;
    } finally {
    try {
    if (pstmt != null) {
    pstmt.close();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    } public static void printArray(String[] a) {
    for (int i = 0; i < a.length; i++) {
    System.out.print(a[i] + " ");
    }
    System.out.println();
    }
      

  32.   

    我先用您写的第一种方法做了测试,我用了1800条数据,用了4个字段,第一次只写进143条,第二次只写进53条,并且最后都报了下面的错误。麻烦您看看代码的哪一部分出了问题??
    个人感觉是con的关闭有问题
    java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]连接占线导致另一个 hstmt
    import java.sql.*;
    import java.util.*;
    import java.io.*;public class testReaderFile{
       public static void main(String[] args) throws Exception {
            try{
            String url = "jdbc:odbc:study";
            String user = "sa";
            String password = "123";
            Connection con = null; 
            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
            con = DriverManager.getConnection(url, user, password);
            String fileName = "C:\\result.txt";
                testReaderFile.readFileWriteBack(fileName, con);
            } catch (Exception e) {
                e.printStackTrace();         
       }
    }
    public static void readFileWriteBack(String fileName, Connection con) throws Exception { 
    String s = ""; 
    File f = new File(fileName); 
    if (!f.exists()) { 
    throw new Exception("file doesn't exist...."); 

    BufferedReader br = null; 
    PreparedStatement pstmt = null; 
    try { 
    br = new BufferedReader(new InputStreamReader(new FileInputStream(f))); while ((s = br.readLine()) != null) { 
    if (s.indexOf("统计量") > 0) { 
    continue; 

    String[] c = s.split("\t"); 
    //System.out.println(c);
    if (c.length == 4) {  
    String sql = "insert into tbl_report(单价,工号,统计量,日期)" 
    + "values(?,?,?,?)"; 
    pstmt = con.prepareStatement(sql); 
    pstmt.setString(1, c[0]); 
    pstmt.setString(2, c[1]);  
    pstmt.setString(3, c[2]); 
    pstmt.setString(4, c[3]);  
    pstmt.execute(); 

    } System.out.println("file write back finished"); 
    } catch (Exception e) {                         
    throw e;                 //可能是这里的异常没处理好,con的关闭有问题。
    } finally { 
    try { 
    if (pstmt != null) {
    pstmt.close(); 
    }
    if (con != null) {
     con.close(); 
    }
    br.close(); 
    } catch (Exception e) { 
    e.printStackTrace(); 



    }
      

  33.   

    失误了,在
    pstmt.execute(); 
    后面加上
    pstmt.close();
    我测试过了,用的oracle数据库。
      

  34.   

    因为是相同的sql,所以用下面的批量提交功能会更好:
    public static void readFileWriteBack(String fileName, Connection con)
    throws Exception {
    String s = "";
    File f = new File(fileName);
    if (!f.exists()) {
    throw new Exception("file doesn't exist....");
    }
    BufferedReader br = null;
    PreparedStatement pstmt = null;
    try {
    br = new BufferedReader(new InputStreamReader(
    new FileInputStream(f)));
    String sql = "insert into tbl_report(单价,工号,统计量,日期)"
    + "values(?,?,?,'2009-12-07')";
    pstmt = con.prepareStatement(sql);
    //循环外部准备好prepareStatement;
    while ((s = br.readLine()) != null) {
    if (s.indexOf("合计") > 0) {
    continue;
    }
    String[] c = s.split("\t");
    printArray(c);
    if (c.length == 3) {
    //加入批量参数
    pstmt.setString(1, c[0]);
    pstmt.setString(2, c[1]);
    pstmt.setString(3, c[2]);
    pstmt.addBatch();
    }
    }
    //一次执行。
    pstmt.executeBatch();
    System.out.println("file write back finished");
    } catch (Exception e) {
    throw e;
    } finally {
    try {
    if (pstmt != null) {
    pstmt.close();
    }
    br.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
      

  35.   

    相应的readListWriteBack修改如下:public static void readListWriteBack(ArrayList<ClassObj> lst, Connection con)
    throws Exception {
    PreparedStatement pstmt = null;
    try {
    // tbl_report是要写回的数据表,最好
    String sql = "insert into tbl_report(单价,工号,统计量,日期)"
    + "values(?,?,?,'2009-12-07')";
    pstmt = con.prepareStatement(sql);
    for (int i = 0; i < lst.size(); i++) {
    ClassObj co = lst.get(i);
    String man = co.getMan();
    if (!man.equals("经理")) {
    pstmt.setString(1, co.getClassGroup());
    pstmt.setString(2, co.getClassGroup());
    pstmt.setString(3, co.getClassGroup());
    pstmt.addBatch();
    }
    }
    pstmt.executeBatch();
    System.out.println("arraylist write back finished");
    } catch (Exception e) {
    throw e;
    } finally {
    try {
    if (pstmt != null) {
    pstmt.close();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
      

  36.   

    调用:OConnection.getCon()就是你前面那一段取Connection的,我另外放了。
    public static void main(String[] args) throws Exception {
    Connection con = null;
    try {
    ArrayList<ClassObj> lst = new ArrayList<ClassObj>();// test6.getResultLst();
    int i = 0;
    while (i++ < 2000) {
    ClassObj obj = new ClassObj();
    obj.setClassId("A" + i);
    obj.setClassGroup("B" + i);
    obj.setClassNo("C" + i);
    obj.setMan("D" + i);
    lst.add(obj);
    }
    String fileName = "E:\\result.dat";
    // String contents = ReadWriteListFile.formatLst(lst);
    // saveFile(fileName, contents);
    con = OConnection.getConn();
    ReadWriteListFile.readListWriteBack(lst, con);
    // readFileWriteBack(fileName, con);
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    if (con != null) {
    con.close();
    }
    }
    }
      

  37.   

    好乱啊,你的SQL可以改为这样的
    我觉得LZ都弄的乱乱的,都是同一个字段,还弄个A,D,H做什么?直接一个A或就用"业务量"这个字段
    如果使用了ClassObj ,就没办法自由了,也就是说添加了字段就不行了
    具体的要求,我也不知道LZ的意思,没说清楚
    select 业务量,单价,员工编号,经理='',地区='' from 表1
    UNION ALL
    select 业务量,单价,员工编号,经理='',地区 from 表2
    UNION ALL
    select 业务量,单价,员工编号,经理,地区='' from 表3";
    这样一个SQL语句就出来了
    而且没有的字段用空字符串代替了 ""
      

  38.   


    我老早向他建议过了,一条sql就可以搞定的。他说需求不定,还是用3个sql好
      

  39.   


    您误会我的意思了,您看分三个SQL写的目的是为了分别为三个结果集加入不同的“组长:XX”字段,像您写的这段代码是有问题的,while(rs.next())已经限制了循环的条件,所以c1.setCaptain("组长:张三")是跑不进来的(不知道是不是这个原因,但是这种写法是跑不起来的),最后我是开了三个 ArrayList<ClassObj>分别装三个SQL结果集,lst,lst2,lst3,然后返回了三个contents,才把三个组长加进去,
         static String formatLst(ArrayList<ClassObj> lst) {
            String contents = "";
            String Band ="组长:张三"   //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
            for (int i = 0; i < lst.size(); i++) {
                contents += Band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"+"\n";
            }
            return contents;
        }     static String formatLst2(ArrayList<ClassObj> lst2) {
            String contents2 = "";
            String Band ="组长:李四"
            for (int i = 0; i < lst2.size(); i++) {
                contents += Band+"\t"+lst2.get(i).getClassBuss() +"\t"+lst2.get(i).getClassId() +"\t"+"\n";
            }
            return contents2;
        }
         static String formatLst3(ArrayList<ClassObj> lst3) {
            String contents3 = "";
            String Band ="组长:王五"
          
           代码重复的很多,但是需求还是满足了,因为三条SQL的组长是不同的,要是用union all装在一起的话,就不好判断分别加入组长了。
      

  40.   

     关于写入数据库还有一个类似的问题,比如在SQL表中增加一个字段“导入数据日期”,txt文件中还是只有前四个字段,“导入数据日期”就是运行程序写入数据库的当前时间,应该怎么写?
    String sql = "insert into tbl_report(单价,工号,统计量,日期,导入数据日期)" + "values(?,?,?,?,'nowDate()')"; 
      

  41.   


    如果是日期型,就用 "values(?,?,?,?,getdate())"; 不要单引号
      

  42.   


    呵呵,sql可以加的。不信你试:
    select 业务量 as A,单价 as B,员工编号 as C,'组长:张三' as D from 表1;
    看看查询结果,是不是D列所有的值都是'组长:张三'
    在select语句中,你可以显式的把常量加进去作为查询结果的该列固定值。你把band作为一个参数传进去,就不用写3个方法了
        static String formatLst(ArrayList <ClassObj> lst ,String band) {
            String contents = "";
           // String Band ="组长:张三"  //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
            for (int i = 0; i < lst.size(); i++) {
                contents += band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"+"\n";
            }
            return contents;
        } 
      

  43.   

    lsh902你加我QQ吧,有时候真替你急
    56525451
      

  44.   

    感谢您给予的帮助,我还是个java初学者,还有许多疑难问题,以后还要麻烦您多帮助,感激不尽。我加你的QQ了。
      

  45.   

    关于合计的问题还是没能解决,还是数据类型犯糊涂了。我把问题仔细的整理了一下,烦请高手帮忙解决!!
    首先关于“单价”这一列,其实是下面的结构,
      单价
    苹果;桔子
    桔子;香蕉;西瓜
    香蕉;苹果
    西瓜
    桔子;西瓜单价列其实是产品的名称,有多种产品的之间用“;”隔开,
    在代码中用HashMap将名称替换为相应的人为规定的单价,然后在while循环中用split(";")拆分然后计算,
    这一步没有问题,
    现在要求合计的话,就要在formatLst里将单价(A)和业务量(B)相乘。单价肯定是Double型了,业务量
    是count(*)出来的数据,应该用int型,但是运算的时候还是报错了。大家帮忙看看数据类型应当如何
    转换,有没有更好的运算方法????
    public static void main(String[] args) 
    {
    .........
    }
        .........
    String sql = "select 单价 as A,业务量 as B,员工编号 as C from 表1";
    ......
    String fa = "";
    ClassObj c1=null;
             while(rs.next()){
              fa = rs.getString("A");
              c1=new ClassObj();
      if(fa.indexOf(";") != -1){
                            double sum = 0;
                            String[] temp = fa.split(";");
                            for(int i = 0 ; i < temp.length; i ++){
                                sum += getPrice(temp[i]);
                            }
                            c1.setClassId(sum);
                        }else {
                            c1.setClassId(getPrice(fa));
                        }
                    c1.setClassGroup(rs.getString("B"));
                    c1.setClassNo(rs.getString("C"));               
                  lst.add(c1);
              } 
      
    private static Map<String,Double> price = new HashMap<String,Double>(0);
      static {
     price.put("苹果", 1d);
     price.put("桔子", 3d);
     price.put("香蕉", 2.5);
     price.put("西瓜", 1.6);
    }
    private static double getPrice(String name){
     Double d = price.get(name);
     return d == null ? 0 : d.doubleValue();
    }

        static String formatLst(ArrayList<ClassObj> lst) {
            String contents = "";
            String total = "";
            for (int i = 0; i < lst.size(); i++) {
           Double hell=lst.get(i).getClassId();//从这开始就范糊涂了,
           int song=lst.get(i).getClassGroup();
      total = String.valueOf((hell).doubleValue*Integer.parseInt(song)); //???????帮忙解决
                contents += lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()
                        +"\t"+ lst.get(i).getClassNo() +"\n";
            }
            return contents;
        }
      

  46.   

    不用在formatLst里面去做,你取数据set到List里面的时候就可以做掉while(rs.next()){
              fa = rs.getString("A");
              c1=new ClassObj();
                  double sum = 0; //提到前面来记录价格
                  if(fa.indexOf(";") != -1){
                            
                            String[] temp = fa.split(";");
                            for(int i = 0 ; i < temp.length; i ++){
                                sum += getPrice(temp[i]);
                            }
                            c1.setClassId(sum);
                        }else {
                            sum = getPrice(fa); //只有一个,将价格记录下来
                            c1.setClassId(getPrice(fa));
                        }
                    int amount = 0;
                    try{
                        //取得数量并转为int
                        amount = Integer.parseInt(rs.getString("B"));
                     }catch(Exception e){
                         //如果有错,表示rs.getString("B")要么空,要么是无法转换的字符串,那么就不管,此时amount=0;
                     }
                    c1.setSong(sum*amount); //看你这里的情况来定,如果合计这个属性在ClassObj里面是double类型,那么就这样。如果是String,那就用 c1.setSong(String.valueOf(sum*amount));
                    c1.setClassGroup(rs.getString("B"));
                    c1.setClassNo(rs.getString("C"));               
                  lst.add(c1);
              } 下面那个犯糊涂的formatLst里面的计算可以去掉。
      

  47.   

    1.(比较弱的问题)我down了jxl.jar的包,我应该把包放到JDK的哪一个文件夹下??是不是还要在系统变量里设置classpath才能正常使用?(我之前只设了bin)
    现在写import jxl.*;不管用,必须import jxl.WorkbookSettings; 用哪个写哪个,而且文件还要写在src下面。否则就是:软件包 jxl 不存在。
    2.代码的灵活性不强,要是向楼上那样要计算单价,合计的话,是不是要写单独的bean和contents??应当如何写??
    3.像之前一样要让新数据跟在旧数据后面跑的话,就是true和flase的那个,我在jxl的doc里找了些类似的方法,但好像没成功,不知道是
    方法没找对,还是没有if文件是否存在??求解。
    我下的是这个jxl包:JExcelAPI的最新版本:jexcelapi_2_6_10.zip
    下载地址:http://sourceforge.net/projects/jexcelapi/files/jexcelapi/2.6.10/jexcelapi_2_6_10.zip 
    class  .....
    {
    public static void writeExcel(String efilePath)throws IOException{
    String url = "jdbc:odbc:study11";
            String user = "WSuser";
            String password = "[email protected]";
            Connection con = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
            try {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                con = DriverManager.getConnection(url,user,password);
                pstmt = con.prepareStatement(sql);
                rs = pstmt.executeQuery();
     
                OutputStream outf = new FileOutputStream(efilePath);       WritableWorkbook  wwb = Workbook.createWorkbook(outf);        WritableSheet ws = wwb.createSheet("sheettest", 0);
    WritableFont font1 = new WritableFont(WritableFont.TIMES,16,WritableFont.BOLD,false,UnderlineStyle.DOUBLE);
    WritableCellFormat format1=new WritableCellFormat(font1);
                format1.setAlignment(jxl.format.Alignment.CENTRE);
    format1.setBackground(Colour.PINK);
        int i=0;
                    int j=0;
           for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {       
              ws.addCell(new Label(k,0,rs.getMetaData().getColumnName(k+1),format1));   
           }
         while(rs.next()){
             System.out.println(rs.getMetaData().getColumnCount());
         for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {
            ws.addCell(new Label(k,j+i+1,rs.getString(k+1)));
            }           i++;
            }
       wwb.write();
        wwb.close();              
            } catch (Exception e) {
            } finally {
                try {
                    if (rs != null)
                        rs.close();
                    if (pstmt != null)
                        pstmt.close();
                    if (con != null)
                        con.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    }
    public static void main(String[] args) {
            try {
    JExcelOperate.writeExcel("C:\\new_excel.xls");
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
    }
    }
      

  48.   

    1.jxl.jar放在你工程的lib下,像你用到的jdbc驱动包等等,都放在你工程的lib下。如果不是ide,就要在-classpath里面把这些jar一个个写进去。
    2.因为你的单价列长度不定(就是你的苹果香蕉个数不定,所以只能那么算,你要另外写个方法也可以,在classobj类内部写一个public count 方法,在设置了单价和数量之后再调用一下去计算总计栏,把总计设为classobj的一个属性,然后你的单价的那个Map做成一个静态类的静态成员变量在ClassObj里面可以直接用。
    3.jxl应该能够追加,你可以先找到对应的已存在的excel文件的最大行数(jxl应该有相关方法来读excel的),然后写数据的时候从最大数据行的下一行开始写。jxl没用过,具体怎么弄你自己研究一下。
      

  49.   

    关于写入的代码,还有些问题要请教,现在有两种情况:
    1.我用的是Microsoft SQL Server 2005在建表的时候,‘合计’这一项是要能实现select sum(合计)函数的所以这项的数据类型在没有小数点的情况下是numeric(18, 0),int(我只用过这两个类型)。有小数点的情况就只能用numeric(18, 1),所以我猜测批量写入的方法就不合适了,pstmt.setString(1, c[0]); 
    pstmt.setString(2, c[1]);  
    pstmt.setInt(3,Integer.parseInt(c[2]));//如果这项是合计,没有小数的情况是否这样写??
    //如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。请问这种情况应当如何改进代码,没有小数的时候,SQL Server表中应该用那种数据类型??写入的代码
    应该怎么改进??有小数点的话pstmt这应该怎么写?
      

  50.   

    不好意思!是我失误了,没有小数点的批量是可以写的,SQL表用的numeric(18, 0)类型,pstmt.setInt(3,Integer.parseInt(c[2]));合计这样写可以写进去。
    现在就是麻烦问一下,有小数点的具体怎么写???
    //如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。
      

  51.   


    如果你的字段类型定义为numeric(18, 1)
    就用for循环里面不管是带不带小数点,都用setBigDecimal(new BigDecimal(c[2]))
      

  52.   


    while ((s = br.readLine()) != null) { 
    if (s.indexOf("合计") > 0) { 
    continue; 

    String[] c = s.split("\t"); 
    printArray(c); 
    if (c.length == 3) { 
    //加入批量参数 
    pstmt.setString(1, c[0]); 
    pstmt.setString(2, c[1]); 
    setBigDecimal(new BigDecimal(c[2])); //是这个意思吗??
    pstmt.addBatch(); 


      

  53.   

    我想把jxl.jar放在JDK的安装目录里,让它想import java.*;那样直接就可以导入包,应该怎么设置啊??
    另外我要是不建立工程,就只写一个*.java的文本,怎样才能正常导入jar包??
      

  54.   


    放jdk目录干吗?
    如果你是web项目,就放在工程下得lib里面。如果你是cs项目,就应该自己建一个lib目录,然后在执行时classpath把这个lib里面得jar包都包含进来。
    如果你就建一个java得文本,那你得到相应目录下去用javac编译,编译得时候指定classpath指向你的jar包位置。
    你去看看java得编译过程,网上一堆。