首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文件编辑程序

文件编辑程序
EN

Code Review用户
提问于 2014-04-25 06:36:45
回答 3查看 539关注 0票数 11

我编写了一个Java类来替换文件中的文本。该文件包含数据库配置,如下所示:

代码语言:javascript
复制
test.properties

#local
db.url=jdbc:oracle:thin:@localhost:test

#db.user=testa
#db.password=testa

db.user=testb
db.password=testb

#db.user=testc
#db.password=testc

#是一个注释字符。现在正在使用db模式testb

下面是我的Java类,可以在模式之间切换

代码语言:javascript
复制
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class SwitchTo
{
  public static void main(String[] args)
  {
    Map<String, String> schemaMap = new HashMap<String, String>();
    schemaMap.put("a", "testa");
    schemaMap.put("b", "testb");
    schemaMap.put("c", "testc");

    String newText = "";
    for (int i = 0; i < args.length; i++)
    {
      newText = args[i];
    }

    String newdb = "";
    newdb = schemaMap.get(newText);
    if (newdb == null || (newdb != null && newdb.length() <= 0))
    {
      System.out.println("Schema not available, please select : ");
      for (Map.Entry<String, String> entry : schemaMap.entrySet())
      {
        System.out.println(entry.getKey() + " for " + entry.getValue());
      }
      return;
    }

    try
    {
      BufferedReader file = new BufferedReader(new FileReader("test.properties"));
      String total = "";
      String line = "";
      while ((line = file.readLine()) != null)
      {
        if (!line.startsWith("#") && line.contains("db.user"))
        {
          line = "#" + line;
        }

        if (!line.startsWith("#") && line.contains("db.password"))
        {
          line = "#" + line;
        }

        if (line.startsWith("#") && line.contains(newdb))
        {
          line = line.substring(1);
        }

        total = total + line + "\n";
      }

      FileOutputStream File = new FileOutputStream("test.properties");
      File.write(total.getBytes());
      System.out.println("Switched to schema " + schemaMap.get(newText));
    }
    catch (FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}

我创建了一个批处理文件来从命令行运行这个程序,如下所示:

代码语言:javascript
复制
switch.bat
java SwitchTo %1

现在在命令行写的时候

代码语言:javascript
复制
c:\> switch a

然后它将在文件中注释testb,而testa将被取消注释。

请对此代码提出其他改进建议。

  1. 使用map存储模式是一个不错的选择吗?
  2. 如何使适应新添加的模式而不需要再次编译该类成为通用的?
  3. 有什么更好的算法来解决这个问题吗?
EN

回答 3

Code Review用户

回答已采纳

发布于 2014-04-25 07:13:25

实际上,这可以更通用。

不要对地图进行硬编码,而是从属性文件中填充它。

因此,将支持文件更改为:

代码语言:javascript
复制
#db.id=a
#db.user=testa
#db.password=testa

db.id=b
db.user=testb
db.password=testb

把你的地图填成这样:

代码语言:javascript
复制
private Map<String, String> schemaMap = new HashMap<String, String>();

public void fillMap() throws FileNotFoundException, IOException {
    String line;
    String key = null;
    String value = null;
    try (BufferedReader file = new BufferedReader(new FileReader("test.properties"))){
        while ((line = file.readLine()) != null) {

            if (line.contains("db.id")) {
                key = line.substring(line.indexOf('='));// could be you have to do an + 1
            }
            if (line.contains("db.user")) {
                value = line.substring(line.indexOf('='));
            }
            if (key!=null && value != null) {
                schemaMap.put(key, value);
                key = null;
                value = null;
            }
        }
    } catch (IOException ex) {
         // report with Logger or System.out what happend.
    }
}

第二:在你的主体中,你使用的是args。

你不检查你有多少个arg,你只需要拿最后一个arg。

也许检查一下你有多少个args是合适的,然后让程序做你想做的事情。(例如使用错误消息退出或使用默认的arg)。

第三:始终关闭资源(在本例中为读者/作者)。

在这里,它是用java 7中可用的试用资源完成的,否则您将需要一个关闭它的最终块。

票数 12
EN

Code Review用户

发布于 2014-04-25 11:16:59

命名

您应该给您的类和变量有意义的名称。

类名不应该是动词,而应该是名词-- SwitchTo也不能真正表达类所做的事情-- DatabaseConfigurationSwitcher会做得更好。

filetotalnewText这样的变量名称在技术上可能是准确的,但它们并不能帮助读者理解它们的含义-- currentPropertiesFileContentsnewPropertiesFileContentsselectedUser将更好地传达含义,并使您的代码更易于阅读。

您应该始终遵守您所选择的语言的命名约定 -- java变量的camelCase -- newdb是一个糟糕的变量名。File更糟。

没有必要在名称中重复容器的类型:schemasschemaMap好。

冗余码

您发现了一种非常奇怪的方法来分配newText变量--您实际上是在给它分配<num of args> + 1时间!没有必要用""来分配它,当然也不需要用简单的arg.length来重写它:

代码语言:javascript
复制
String newText = args[args.length - 1];

就行了。我能想到的可能驱使您编写这段奇怪代码的唯一原因是您担心args将是空的,在这种情况下您可以添加:

代码语言:javascript
复制
String newText = (args == null || args.length == 0) ? "" : args[args.length - 1];

当然,正如@chillworld所建议的,两者都是错误的,因为您应该检查是否有一个论点是这样的:

代码语言:javascript
复制
if (args.length != 1) throw new Exception("Give only one argument");
String newText = args[0];

假设

出于某种原因,您假设用户名和密码总是相等的,并且在编译时就知道了。如果是这样的话,您本可以让您的生活更轻松,而不是在代码中注释和不注释行,您可以简单地重写该部分,因为您知道它的值:

代码语言:javascript
复制
test.properties

#local
db.url=jdbc:oracle:thin:@localhost:test

#### overwrite everything below this line with db.user=user;db.password=user ####
db.user=testa
db.password=testa

当然,更好的解决方案不是假设您在编译时知道用户名或密码,而是使用外部存储库来保存这些信息(就像@chillworld建议的那样,即使属性文件本身也可能是它)。

串级联

使用String变量来收集代码中的所有行并不是一个好主意,因为它会生成许多新的对象。StringBuilder是一个更好的类型,但在您的情况下。

关闭资源

打开一个文件读取器,然后打开一个文件编写器,但是永远不会close它们!这是非常有问题的,因为您留下了打开的文件句柄,这可能会导致严重的内存泄漏。的确,当进程退出时,java将关闭所有打开的句柄,但是您不应该指望它!

不要抓住你处理不了的

您有一个try块和两个catch子句,它们只会将异常输出到控制台。

更好的方法是声明main(String[] args) throws FileNotFoundException, IOException,甚至不编写try块。

这样,在发生错误时,不仅会在控制台中打印其堆栈跟踪(通过错误流),而且还会通知控制台命令异常结束,命令用户将能够引用该命令(查看errorlevel)。

票数 7
EN

Code Review用户

发布于 2014-04-29 09:50:52

除了“冷世界”和“贾马尔”的答案之外

使用java.nio而不是java.io

代码语言:javascript
复制
private Map<String, String> schemaMap = new HashMap<>();

public void fillMap() throws IOException {

    String key = null;
    String value = null;

    Path path = Paths.get("test.properties");
    try {
        List<String> lines = Files.readAllLines(path, Charset.defaultCharset());

        for (String line : lines) {

            if (line.contains("db.id")) {
                key = line.substring(line.indexOf('='));// could be you have to do an + 1
            }

            if (line.contains("db.user")) {
                value = line.substring(line.indexOf('='));
            }

            if (key != null && value != null) {
                schemaMap.put(key, value);
                key = null;
                value = null;
            }
        }
    } catch (IOException e) {
        // report with Logger or System.out what happend.
    }
}
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/48122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档