Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
IndexOutput.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using Lucene.Net.Support;
20 using UnicodeUtil = Lucene.Net.Util.UnicodeUtil;
21 
22 namespace Lucene.Net.Store
23 {
24 
25  /// <summary>Abstract base class for output to a file in a Directory. A random-access
26  /// output stream. Used for all Lucene index output operations.
27  /// </summary>
28  /// <seealso cref="Directory">
29  /// </seealso>
30  /// <seealso cref="IndexInput">
31  /// </seealso>
32  public abstract class IndexOutput : IDisposable
33  {
34  /// <summary>Writes a single byte.</summary>
35  /// <seealso cref="IndexInput.ReadByte()">
36  /// </seealso>
37  public abstract void WriteByte(byte b);
38 
39  /// <summary>Writes an array of bytes.</summary>
40  /// <param name="b">the bytes to write
41  /// </param>
42  /// <param name="length">the number of bytes to write
43  /// </param>
44  /// <seealso cref="IndexInput.ReadBytes(byte[],int,int)">
45  /// </seealso>
46  public virtual void WriteBytes(byte[] b, int length)
47  {
48  WriteBytes(b, 0, length);
49  }
50 
51  /// <summary>Writes an array of bytes.</summary>
52  /// <param name="b">the bytes to write
53  /// </param>
54  /// <param name="offset">the offset in the byte array
55  /// </param>
56  /// <param name="length">the number of bytes to write
57  /// </param>
58  /// <seealso cref="IndexInput.ReadBytes(byte[],int,int)">
59  /// </seealso>
60  public abstract void WriteBytes(byte[] b, int offset, int length);
61 
62  /// <summary>Writes an int as four bytes.</summary>
63  /// <seealso cref="IndexInput.ReadInt()">
64  /// </seealso>
65  public virtual void WriteInt(int i)
66  {
67  WriteByte((byte) (i >> 24));
68  WriteByte((byte) (i >> 16));
69  WriteByte((byte) (i >> 8));
70  WriteByte((byte) i);
71  }
72 
73  /// <summary>Writes an int in a variable-length format. Writes between one and
74  /// five bytes. Smaller values take fewer bytes. Negative numbers are not
75  /// supported.
76  /// </summary>
77  /// <seealso cref="IndexInput.ReadVInt()">
78  /// </seealso>
79  public virtual void WriteVInt(int i)
80  {
81  while ((i & ~ 0x7F) != 0)
82  {
83  WriteByte((byte) ((i & 0x7f) | 0x80));
84  i = Number.URShift(i, 7);
85  }
86  WriteByte((byte) i);
87  }
88 
89  /// <summary>Writes a long as eight bytes.</summary>
90  /// <seealso cref="IndexInput.ReadLong()">
91  /// </seealso>
92  public virtual void WriteLong(long i)
93  {
94  WriteInt((int) (i >> 32));
95  WriteInt((int) i);
96  }
97 
98  /// <summary>Writes an long in a variable-length format. Writes between one and five
99  /// bytes. Smaller values take fewer bytes. Negative numbers are not
100  /// supported.
101  /// </summary>
102  /// <seealso cref="IndexInput.ReadVLong()">
103  /// </seealso>
104  public virtual void WriteVLong(long i)
105  {
106  while ((i & ~ 0x7F) != 0)
107  {
108  WriteByte((byte) ((i & 0x7f) | 0x80));
109  i = Number.URShift(i, 7);
110  }
111  WriteByte((byte) i);
112  }
113 
114  /// <summary>Writes a string.</summary>
115  /// <seealso cref="IndexInput.ReadString()">
116  /// </seealso>
117  public virtual void WriteString(System.String s)
118  {
119  UnicodeUtil.UTF8Result utf8Result = new UnicodeUtil.UTF8Result();
120  UnicodeUtil.UTF16toUTF8(s, 0, s.Length, utf8Result);
121  WriteVInt(utf8Result.length);
122  WriteBytes(utf8Result.result, 0, utf8Result.length);
123  }
124 
125  /// <summary>Writes a sub sequence of characters from s as the old
126  /// format (modified UTF-8 encoded bytes).
127  /// </summary>
128  /// <param name="s">the source of the characters
129  /// </param>
130  /// <param name="start">the first character in the sequence
131  /// </param>
132  /// <param name="length">the number of characters in the sequence
133  /// </param>
134  /// <deprecated> -- please pre-convert to utf8 bytes
135  /// instead or use <see cref="WriteString" />
136  /// </deprecated>
137  [Obsolete("-- please pre-convert to utf8 bytes instead or use WriteString")]
138  public virtual void WriteChars(System.String s, int start, int length)
139  {
140  int end = start + length;
141  for (int i = start; i < end; i++)
142  {
143  int code = (int) s[i];
144  if (code >= 0x01 && code <= 0x7F)
145  WriteByte((byte) code);
146  else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0)
147  {
148  WriteByte((byte) (0xC0 | (code >> 6)));
149  WriteByte((byte) (0x80 | (code & 0x3F)));
150  }
151  else
152  {
153  WriteByte((byte) (0xE0 | (Number.URShift(code, 12))));
154  WriteByte((byte) (0x80 | ((code >> 6) & 0x3F)));
155  WriteByte((byte) (0x80 | (code & 0x3F)));
156  }
157  }
158  }
159 
160  /// <summary>Writes a sub sequence of characters from char[] as
161  /// the old format (modified UTF-8 encoded bytes).
162  /// </summary>
163  /// <param name="s">the source of the characters
164  /// </param>
165  /// <param name="start">the first character in the sequence
166  /// </param>
167  /// <param name="length">the number of characters in the sequence
168  /// </param>
169  /// <deprecated> -- please pre-convert to utf8 bytes instead or use <see cref="WriteString" />
170  /// </deprecated>
171  [Obsolete("-- please pre-convert to utf8 bytes instead or use WriteString")]
172  public virtual void WriteChars(char[] s, int start, int length)
173  {
174  int end = start + length;
175  for (int i = start; i < end; i++)
176  {
177  int code = (int) s[i];
178  if (code >= 0x01 && code <= 0x7F)
179  WriteByte((byte) code);
180  else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0)
181  {
182  WriteByte((byte) (0xC0 | (code >> 6)));
183  WriteByte((byte) (0x80 | (code & 0x3F)));
184  }
185  else
186  {
187  WriteByte((byte) (0xE0 | (Number.URShift(code, 12))));
188  WriteByte((byte) (0x80 | ((code >> 6) & 0x3F)));
189  WriteByte((byte) (0x80 | (code & 0x3F)));
190  }
191  }
192  }
193 
194  private static int COPY_BUFFER_SIZE = 16384;
195  private byte[] copyBuffer;
196 
197  /// <summary>Copy numBytes bytes from input to ourself. </summary>
198  public virtual void CopyBytes(IndexInput input, long numBytes)
199  {
200  System.Diagnostics.Debug.Assert(numBytes >= 0, "numBytes=" + numBytes);
201  long left = numBytes;
202  if (copyBuffer == null)
203  copyBuffer = new byte[COPY_BUFFER_SIZE];
204  while (left > 0)
205  {
206  int toCopy;
207  if (left > COPY_BUFFER_SIZE)
208  toCopy = COPY_BUFFER_SIZE;
209  else
210  toCopy = (int) left;
211  input.ReadBytes(copyBuffer, 0, toCopy);
212  WriteBytes(copyBuffer, 0, toCopy);
213  left -= toCopy;
214  }
215  }
216 
217  /// <summary>Forces any buffered output to be written. </summary>
218  public abstract void Flush();
219 
220  /// <summary>Closes this stream to further operations. </summary>
221  [Obsolete("Use Dispose() instead.")]
222  public void Close()
223  {
224  Dispose();
225  }
226 
227  /// <summary>Closes this stream to further operations. </summary>
228  public void Dispose()
229  {
230  Dispose(true);
231  }
232 
233  protected abstract void Dispose(bool disposing);
234 
235  /// <summary>Returns the current position in this file, where the next write will
236  /// occur.
237  /// </summary>
238  /// <seealso cref="Seek(long)">
239  /// </seealso>
240  public abstract long FilePointer { get; }
241 
242  /// <summary>Sets current position in this file, where the next write will occur.</summary>
243  /// <seealso cref="FilePointer()">
244  /// </seealso>
245  public abstract void Seek(long pos);
246 
247  /// <summary>The number of bytes in the file. </summary>
248  public abstract long Length { get; }
249 
250  /// <summary>Set the file length. By default, this method does
251  /// nothing (it's optional for a Directory to implement
252  /// it). But, certain Directory implementations (for
253  /// </summary>
254  /// <seealso cref="FSDirectory"> can use this to inform the
255  /// underlying IO system to pre-allocate the file to the
256  /// specified size. If the length is longer than the
257  /// current file length, the bytes added to the file are
258  /// undefined. Otherwise the file is truncated.
259  /// </seealso>
260  /// <param name="length">file length
261  /// </param>
262  public virtual void SetLength(long length)
263  {
264  }
265 
266 
267  // map must be Map<String, String>
268  public virtual void WriteStringStringMap(System.Collections.Generic.IDictionary<string,string> map)
269  {
270  if (map == null)
271  {
272  WriteInt(0);
273  }
274  else
275  {
276  WriteInt(map.Count);
277  foreach (var entry in map)
278  {
279  WriteString(entry.Key);
280  WriteString(entry.Value);
281  }
282  }
283  }
284  }
285 }