我编写了一个Java类来替换文件中的文本。该文件包含数据库配置,如下所示:
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类,可以在模式之间切换
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();
}
}
}我创建了一个批处理文件来从命令行运行这个程序,如下所示:
switch.bat
java SwitchTo %1现在在命令行写的时候
c:\> switch a然后它将在文件中注释testb,而testa将被取消注释。
请对此代码提出其他改进建议。
发布于 2014-04-25 07:13:25
实际上,这可以更通用。
不要对地图进行硬编码,而是从属性文件中填充它。
因此,将支持文件更改为:
#db.id=a
#db.user=testa
#db.password=testa
db.id=b
db.user=testb
db.password=testb把你的地图填成这样:
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中可用的试用资源完成的,否则您将需要一个关闭它的最终块。
发布于 2014-04-25 11:16:59
命名
您应该给您的类和变量有意义的名称。
类名不应该是动词,而应该是名词-- SwitchTo也不能真正表达类所做的事情-- DatabaseConfigurationSwitcher会做得更好。
像file、total和newText这样的变量名称在技术上可能是准确的,但它们并不能帮助读者理解它们的含义-- currentPropertiesFileContents、newPropertiesFileContents和selectedUser将更好地传达含义,并使您的代码更易于阅读。
您应该始终遵守您所选择的语言的命名约定 -- java变量的camelCase -- newdb是一个糟糕的变量名。File更糟。
没有必要在名称中重复容器的类型:schemas比schemaMap好。
冗余码
您发现了一种非常奇怪的方法来分配newText变量--您实际上是在给它分配<num of args> + 1时间!没有必要用""来分配它,当然也不需要用简单的arg.length来重写它:
String newText = args[args.length - 1];就行了。我能想到的可能驱使您编写这段奇怪代码的唯一原因是您担心args将是空的,在这种情况下您可以添加:
String newText = (args == null || args.length == 0) ? "" : args[args.length - 1];当然,正如@chillworld所建议的,两者都是错误的,因为您应该检查是否有一个论点是这样的:
if (args.length != 1) throw new Exception("Give only one argument");
String newText = args[0];假设
出于某种原因,您假设用户名和密码总是相等的,并且在编译时就知道了。如果是这样的话,您本可以让您的生活更轻松,而不是在代码中注释和不注释行,您可以简单地重写该部分,因为您知道它的值:
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)。
发布于 2014-04-29 09:50:52
除了“冷世界”和“贾马尔”的答案之外
使用java.nio而不是java.io
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.
}
}https://codereview.stackexchange.com/questions/48122
复制相似问题