none
分割字符串的一个小问题 RRS feed

  • 问题

  • 在一个程序中存在这么一句

    首先magicos.url这个文件的类容读到StrAllText

    Dim StrAllText as String= My.computer.filesystem.readalltext("c:\magicos.url") 

    然后使用换行来分割这个文件的类容到一个字符串数组中

    Dim StrLines() as String = StrAllText . Split(New String() {ControlChars.Crlf}, StringSplitOptions.RemoveEmptyEntries)

    ------------

    我的问题是那个 Split(New String() {ControlChars.Crlf}) 我看MSDN上面说这个Split的第一个是分割参数

    按照我的理解这里直接 Split(ControlChars.Crlf)不就可以了么

    Split(New String() {ControlChars.Crlf}, StringSplitOptions.RemoveEmptyEntries)  这个前面的New String()  起到什么作用?或者 固定格式?因为删除它这段就会报错,貌似和后面的参数 StringSplitOptions.RemoveEmptyEntries 有联系- -

    还希望知道的老师说明一下

    谢谢 !
    2009年12月4日 7:25

答案

  • 的确成功通过了VB编译器的编译!
    VB编译器的这个行为的确有些出乎预料!
    这样的代码在C#下无论如何都不可能通过编译,会出现两个编译错误:
    错误    1    与“string.Split(params char[])”最匹配的重载方法具有一些无效参数   
    错误    2    参数“1”: 无法从“string”转换为“char[]”   


    让我们仔细来看看VB编译器都做了什么样的工作,这是生成的IL代码,你直接看我的注释就可以了:
    .method public static void  Main() cil managed
    {
      .entrypoint
      .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
      // 代码大小       44 (0x2c)
      .maxstack  4
      .locals init ([0] string stralltext,
               [1] string[] StrLines,
               [2] char[] VB$t_array$S0)
      IL_0000:  nop
      IL_0001:  call       class ConsoleApplication1.My.MyComputer ConsoleApplication1.My.MyProject::get_Computer()
      IL_0006:  callvirt   instance class [Microsoft.VisualBasic]Microsoft.VisualBasic.MyServices.FileSystemProxy [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.ServerComputer::get_FileSystem()
      IL_000b:  ldstr      "c:\\magic.txt"
      IL_0010:  callvirt   instance string [Microsoft.VisualBasic]Microsoft.VisualBasic.MyServices.FileSystemProxy::ReadAllText(string)
      IL_0015:  stloc.0
      IL_0016:  ldloc.0
      IL_0017:  ldc.i4.1
      IL_0018:  newarr     [mscorlib]System.Char      //这里VB编译器自动构造了一个Char数组
      IL_001d:  stloc.2
      IL_001e:  ldloc.2
      IL_001f:  ldc.i4.0
      IL_0020:  ldc.i4.s   97
      IL_0022:  stelem.i2
      IL_0023:  ldloc.2
      IL_0024:  callvirt   instance string[] [mscorlib]System.String::Split(char[])       //这里调用的是String.Split(char[])这个重载
      IL_0029:  stloc.1
      IL_002a:  nop
      IL_002b:  ret
    } // end of method Module1::Main

    VB.NET编译器会在需要的时候把string转化成char数组!
    周雪峰
    • 已标记为答案 YiChun Chen 2009年12月7日 11:37
    2009年12月5日 7:48
    版主
  • 你好!
         这行不可能成功:StrAllText . Split(ControlChars.CrLf)
         Split的第一个参数必须是string数组或char数组或char数组,而ControlChars.CrLf是string类型的,不可能成功!
    周雪峰
    2009年12月4日 15:10
    版主

全部回复

  • 你好!
         Split的第一个参数要求是String的数组,所以这里需要构造一个String数组!
    周雪峰
    2009年12月4日 10:51
    版主
  • 但是在这里我前面已经定义了一个数组来储存被分割的项了

    Dim StrLines() as String

    另外 如果不添加后面的参数 就可以这样使用
    Dim StrLines() as String = StrAllText . Split(ControlChars.Crlf)

    不知道这是什么原因?还希望能解释一下。。谢谢

    2009年12月4日 13:48
  • 你好!
         这行不可能成功:StrAllText . Split(ControlChars.CrLf)
         Split的第一个参数必须是string数组或char数组或char数组,而ControlChars.CrLf是string类型的,不可能成功!
    周雪峰
    2009年12月4日 15:10
    版主
  • 但是我在VS2008下编译确实成功了

    我调试的时候是这样写代码的

            Dim stralltext As String = My.Computer.FileSystem.ReadAllText("c:\magic.txt")

            Dim StrLines() As String = stralltext.Split(ControlChars.CrLf)

    运行完第2句后 StrLines这个字符串数组被用ControlChars.CrLf分割成几份 只不过不带参数的情况下不能移除文件中的空行

    2009年12月5日 7:17
  • 的确成功通过了VB编译器的编译!
    VB编译器的这个行为的确有些出乎预料!
    这样的代码在C#下无论如何都不可能通过编译,会出现两个编译错误:
    错误    1    与“string.Split(params char[])”最匹配的重载方法具有一些无效参数   
    错误    2    参数“1”: 无法从“string”转换为“char[]”   


    让我们仔细来看看VB编译器都做了什么样的工作,这是生成的IL代码,你直接看我的注释就可以了:
    .method public static void  Main() cil managed
    {
      .entrypoint
      .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
      // 代码大小       44 (0x2c)
      .maxstack  4
      .locals init ([0] string stralltext,
               [1] string[] StrLines,
               [2] char[] VB$t_array$S0)
      IL_0000:  nop
      IL_0001:  call       class ConsoleApplication1.My.MyComputer ConsoleApplication1.My.MyProject::get_Computer()
      IL_0006:  callvirt   instance class [Microsoft.VisualBasic]Microsoft.VisualBasic.MyServices.FileSystemProxy [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.ServerComputer::get_FileSystem()
      IL_000b:  ldstr      "c:\\magic.txt"
      IL_0010:  callvirt   instance string [Microsoft.VisualBasic]Microsoft.VisualBasic.MyServices.FileSystemProxy::ReadAllText(string)
      IL_0015:  stloc.0
      IL_0016:  ldloc.0
      IL_0017:  ldc.i4.1
      IL_0018:  newarr     [mscorlib]System.Char      //这里VB编译器自动构造了一个Char数组
      IL_001d:  stloc.2
      IL_001e:  ldloc.2
      IL_001f:  ldc.i4.0
      IL_0020:  ldc.i4.s   97
      IL_0022:  stelem.i2
      IL_0023:  ldloc.2
      IL_0024:  callvirt   instance string[] [mscorlib]System.String::Split(char[])       //这里调用的是String.Split(char[])这个重载
      IL_0029:  stloc.1
      IL_002a:  nop
      IL_002b:  ret
    } // end of method Module1::Main

    VB.NET编译器会在需要的时候把string转化成char数组!
    周雪峰
    • 已标记为答案 YiChun Chen 2009年12月7日 11:37
    2009年12月5日 7:48
    版主
  • 谢谢周大哥

    总算看明白了

    但是这里我还想问一个相关问题

    我在MSDN中查到Split如下两个重载版本 我想问一下 Unicode 字符数组 和  普通的字符数组他们有什么区别?
    因为我在做测试的时候他们两个返回的似乎都是一样的

    Split(Char [], StringSplitOptions) 返回的字符串数组包含此字符串中的子字符串(由指定 Unicode 字符数组的元素分隔)。参数指定是否返回空数组元素。
    Split(String [], StringSplitOptions) 回的字符串数组包含此字符串中的子字符串(由指定字符串数组的元素分隔)。参数指定是否返回空数组元素。
    2009年12月8日 7:34
  • 你好!
         这个没有区别,实际上string类型表示文本,即一系列 Unicode 字符。
    周雪峰
    2009年12月8日 8:04
    版主
  • 呵呵 谢谢你了 ~ 全部明白了~!
    2009年12月8日 14:01
  • 不客气啊!
    周雪峰
    2009年12月8日 15:36
    版主