读取文件修改一行并将文件写回 [英] Read file modify a line and write file back out

查看:77
本文介绍了读取文件修改一行并将文件写回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个函数,可以读取文件并修改一行,然后将其写回。代码有点复杂和复杂。请指导我一些示例代码,我可以用更专业的方式完成此任务。



谢谢。



这是代码:



  public   static   void  manageAllTests( String  obr_tests, string  obx_tests)
{
String [] ind;
String [] existingElements;
String [] newElements;
int found = 0 ;
int lineno = -1;
string elements = ;
StreamReader textIn = new StreamReader( new FileStream(ReportFolder + \\allTests.txt,FileMode.OpenOrCreate,FileAccess.Read));
while (textIn.Peek()!= -1)
{
lineno + = 1 ;
string line = textIn.ReadLine();
ind = line.Split(' \t');
if (ind [ 0 ] == obr_tests)
{
found = 1 ;
break ;
}
}
textIn.Close();
if (found == 1
{
int curlineno = 0 ;
StringBuilder buffer = new StringBuilder();
StreamReader textInRem = new StreamReader( new FileStream(ReportFolder + \\alltests.txt,FileMode.OpenOrCreate,FileAccess.ReadWrite));
while (textInRem.Peek()!= -1)
{
string curline = textInRem.ReadLine();
if (curlineno!= lineno)
{
buffer.AppendLine(curline);
}
else
{
ind = curline.Split('' \t');
elements = ind [ 1 ];
}

curlineno + = 1 ;
}
textInRem.Close();
StreamWriter textOutm = new StreamWriter( new FileStream(ReportFolder + \\alltests.txt,FileMode.Create,FileAccess.Write));
textOutm.Write(buffer.ToString());
textOutm.Close();
}

existingElements = elements.Split(' |' );
newElements = obx_tests.Split(' |');
foreach string e in newElements)
{
int found1 = 0 ;
for int x = 1 ; x < existingElements.Length; x ++)
{
if (e == existingElements [x])
{
found1 = 1 ;
}

}
如果(found1 == 0
{

if (elements ==
{
elements = e;

}
else
{
elements = elements + | + e;
}
existingElements = elements.Split(' |');
}
}

StreamWriter textOut = new StreamWriter( new FileStream(ReportFolder + \\alltests.txt,FileMode.Append,FileAccess 。写));
textOut.WriteLine(obr_tests + ' \t' + elements);
textOut.Close();
}

解决方案

问题列表可能比你的代码更长,并且给你一个代码示例几乎不会教你多少。相反,你应该听一些批评,学习你必须学习的东西,再写一遍,听批评,等等。首先,代码本身并不好或坏(当然,原则上它肯定是坏的)。当知道它的目标以及要求时,这可能是一件好事,而这是你无需指定的事情。因此,由于缺乏规范,您无法提供真正全面的建议。



代码显示没有上下文。哪里是 ReportFolder



当你在静态方法中使用ReportFolder时,它意味着 ReportFolder(也许其他东西也是静态的)。这绝对是坏事。数据不应该是静态的。您是否了解与静态相关的线程问题以及堆栈变量不存在的线程问题以及在不同线程中使用复杂类型的不同实例时?无论如何,请不要告诉我们你没有使用线程,它不能证明失败是正确的。没有理由声明静态数据成员。同时,方法通常需要是静态的,但是它应该是仅使用参数和返回值或对象的方法,而不是其他方法。例如方法,使用它们的声明类型的实例成员进行操作是可以的,非常合适。可以通过this访问它们。



文件名应该是参数方法,未在其中声明。



现在,立即常数\\alltests.txt被宣布更多的事实然后曾经不是一个bug,这是一个犯罪。你明白你刚刚杀死了你项目的可支持性吗?如果你的代码中必须有一些字符串常量,那么它应该显式生成为 const 。通常,常量字符串属于嵌入在可执行模块中的资源甚至是配置文件。



您永远不应该使用重复的连接,例如 obr_tests +' \t'+ elements)。字符串是不可变的。我甚至要解释其含义吗?您应该改为:

  string  someContent =  string .Format(  {0} \t {1},obr_tests,elements) ; 





由于类似的原因,您对字符串的使用效率通常非常低。



不是错误,但是: obr_tests 之类的名称违反(相当不错)Microsoft命名约定。你不应该使用下划线;并且从不使用非常见的缩写。使用,比如说 someTests (这只是一个提示;而不是some应该是语义上合理的东西)。



永远不要使用,使用 string.Empty 。这不是一个错误,但如果您开始消灭立即常量,这将极大地帮助您。在大多数文件中全局搜索:没有?很棒!许多开发人员从不对任何直接常量进行硬编码,但是0,1和null。



您使用的模式 StreamWriter 和其他与流相关的类型是完全错误的。(这会有效,但这实际上是一个错误+加上代码设计错误。)想想在流关闭之前有一些异常。你使用 FileStream 完全没有意义。应该是:

  string  someFileName =  //   ...  
using (StreamWriter writer = new StreamWriter(someFileName)){
writer.Write(buffer.ToString());
// 什么是缓冲区?如果是字符串,.ToString()是多余的
} // writer.Dis这里会自动调用pose



请参阅: http://msdn.microsoft.com/en-us/library/yh598w02.aspx [ ^ ]。



你的 textIn.Peek()看起来毫无意义。你想要达到什么目的?也许您只需要一次编写所有内容,这对于或多或少的小文件是最好的。你说你需要阅读行并修改一行。做到这一点,除了 ReadLine 之外你不需要任何东西。



很可能你的拆分调用需要选项 StringSplitOptions.RemoveEmptyEntries 。有时候你可能没有tab,但是有一些偶然的空格字符?这种不准确的格式很难用肉眼检测,因此请使用:

http:// msdn.microsoft.com/en-us/library/tabh47cf.aspx [ ^ ],

http://msdn.microsoft.com/en-us/library/system.stringsplitoptions.aspx [ ^ ]。



使用FxCop:

< a href =http://en.wikipedia.org/wiki/FxCop> http://en.wikipedia.org/wiki/FxCop [ ^ ],

http://msdn.microsoft.com/en-us/library/bb429476.aspx [ ^ ]。



将您的方法分解为更小的方法,每个方法都有明确的目标和简单的实施。



对,你的思维看起来很复杂,但你可以自己训练。用简单的英语写下所有中间步骤。如果您能清楚地解释他们的工作,您可以更清楚地编写代码。当你获得良好的经验时,这个阶段将不再需要,但一开始它会教你很多。



-SA

I have written a function which can read in a file and modify a line and then write it back out. The code is somewhat complicated and convoluted. Please direct me to some sample code where I can accomplish this in a more professional manner.

Thank you.

Here's the code:

public static void manageAllTests(String obr_tests,string obx_tests)
        {
            String[] ind;
            String [] existingElements;
            String[] newElements;
            int found = 0;
            int lineno = -1;
            string elements = "";
            StreamReader textIn = new StreamReader(new FileStream(ReportFolder + "\\allTests.txt", FileMode.OpenOrCreate, FileAccess.Read));
            while (textIn.Peek() != -1)
            {
                lineno += 1;
                string line = textIn.ReadLine();
                ind = line.Split('\t');
                if (ind[0] == obr_tests)
                {
                    found = 1;
                    break;
                }
            }
            textIn.Close();
            if (found == 1)
            {
                int curlineno = 0;
                StringBuilder buffer = new StringBuilder();
                StreamReader textInRem = new StreamReader(new FileStream(ReportFolder + "\\alltests.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite));
                while (textInRem.Peek() != -1)
                {
                    string curline = textInRem.ReadLine();
                    if (curlineno != lineno)
                    {
                        buffer.AppendLine(curline);
                    }
                    else
                    {
                        ind = curline.Split('\t');
                        elements = ind[1];
                    }

                    curlineno += 1;
                }
                textInRem.Close();
                StreamWriter textOutm = new StreamWriter(new FileStream(ReportFolder + "\\alltests.txt", FileMode.Create, FileAccess.Write));
                textOutm.Write(buffer.ToString());
                textOutm.Close();
            }

            existingElements = elements.Split('|');
            newElements = obx_tests.Split('|');
            foreach (string e in newElements)
            {
                int found1 = 0;
                for (int x = 1; x < existingElements.Length; x++)
                {
                    if (e == existingElements[x])
                    {
                        found1 = 1;
                    }

                }
                if (found1 == 0)
                {

                    if ( elements == "")
                    {
                        elements = e;

                    }
                    else
                    {
                            elements = elements + "|" + e;
                    }
                    existingElements = elements.Split('|');
                }
             }

            StreamWriter textOut = new StreamWriter(new FileStream(ReportFolder + "\\alltests.txt", FileMode.Append, FileAccess.Write));
            textOut.WriteLine(obr_tests + '\t' + elements);
            textOut.Close();
            }

解决方案

The list of problems can be much longer than your code iself, and giving you a code sample would hardly teach you much. Instead, you should listen to some criticism, learn what you have to learn, write it again, listen to criticism, and so on. First of all, the code cannot be good or bad by itself (well, it can certainly be bad in principle, of course). It can be good a bad when the goal of it is known, as well as requirements, and this is something you did not bother to specify. So, you cannot hope for a really comprehensive advice, due to the lack of specifications.

Code is showed without the context. Where is "ReportFolder"?

As you use "ReportFolder" in a static method, it means that "ReportFolder" (and maybe something else is also static). This is absolutely bad. Data should not be static. Do you understand threading problems related to static and not existing for stack variables and when you use different instances of complex type in different threads? Anyway, please don't tell us you are not using threads, it won't justify the failure. There is no a reason to declare static data members. At the same time, methods are often required to be static, but then it should be methods using only the parameters and return value or object, nothing else. For instance methods, it's OK and quite appropriate to operate with their declaring type's instance members, which are accessible via "this".

File name should be a parameter of the method, not declared inside it.

Now, the fact that the immediate constant "\\alltests.txt" is declared more then once is not a bug, it's a crime. Do you understand that you just killed the supportability of your project? If you have to have some string constants in your code, it should be explicitly generated as const. Very often, constant strings belong to resource embedded in the executable module or even configuration files.

You should never use repeated concatenations like obr_tests + '\t' + elements). Strings are immutable. Do I even have to explain the implications? You should write instead:

string someContent = string.Format("{0}\t{1}", obr_tests, elements);



Your use of string looks generally very inefficient, by similar reasons.

Not a bug, but: the names like obr_tests violate (pretty good) Microsoft naming conventions. You should not use underscores; and never use non-common abbreviations. Use, say someTests (this is just a hint; instead of "some" should be something semantically sensible).

Never use "", use string.Empty. This is not a bug, but this will greatly help you if you start exterminating immediate constants. Search globally in most files: no "? Great! Many developers never hard-code any immediate constants but 0, 1 and null.

Your pattern of using StreamWriter and other stream-related types is totally wrong. (This will work, but this is actually a bug + plus code design mistake.) Think about having some exception before the stream is closed. Your use of FileStream is totally pointless. Should be:

string someFileName = //...
using (StreamWriter writer = new StreamWriter(someFileName)) {
   writer.Write(buffer.ToString()); 
   // what is "buffer"? If it is a string, .ToString() is redundant
} // writer.Dispose is called automatically here


Please see: http://msdn.microsoft.com/en-us/library/yh598w02.aspx[^].

Your textIn.Peek() looks totally pointless. What did you want to achieve? Maybe you simply need to write all the contents at once, which is the best for more or less small files. You say that you needed to read lines and modify one. Do exactly that, than you won't need anything but ReadLine.

It is most likely that your Split calls require the option StringSplitOptions.RemoveEmptyEntries. Isn't likely that sometimes you may have not tab, but tabs with some accidental space characters? Such inaccurate formatting is hard to detect visually, so use:
http://msdn.microsoft.com/en-us/library/tabh47cf.aspx[^],
http://msdn.microsoft.com/en-us/library/system.stringsplitoptions.aspx[^].

Use FxCop:
http://en.wikipedia.org/wiki/FxCop[^],
http://msdn.microsoft.com/en-us/library/bb429476.aspx[^].

Break your method into smaller methods each having clear goal and simple implementation.

Right, your thinking looks convoluted, but you can train yourself. Write all intermediate steps in plain English. If you can clearly explain what they do, you can easier code them clearly. When you gain good experience, this stage won't be needed, but at first it will teach you a lot.

—SA


这篇关于读取文件修改一行并将文件写回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆