diff --git a/core/base/inc/TString.h b/core/base/inc/TString.h
index 1ddf303d3b28aa48ff7501a2ac344312b592d4c1..1f7fd1e193d51b3de6ae15346747509ab8494e43 100644
--- a/core/base/inc/TString.h
+++ b/core/base/inc/TString.h
@@ -208,7 +208,7 @@ protected:
    enum { kAlignment = 16 };
    static Ssiz_t  Align(Ssiz_t s) { return (s + (kAlignment-1)) & ~(kAlignment-1); }
    static Ssiz_t  Recommend(Ssiz_t s) { return (s < kMinCap ? kMinCap : Align(s+1)) - 1; }
-   static Ssiz_t  AdjustCapacity(Ssiz_t nc);
+   static Ssiz_t  AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap);
    
 private:
    Bool_t         IsLong() const { return Bool_t(fRep.fShort.fSize & kShortMask); }
@@ -232,9 +232,9 @@ private:
    char          *GetPointer() { return IsLong() ? GetLongPointer() : GetShortPointer(); }
    const char    *GetPointer() const { return IsLong() ? GetLongPointer() : GetShortPointer(); }
 #ifdef R__BYTESWAP
-   Ssiz_t         MaxSize() const { return kMaxInt - 1; }
+   static Ssiz_t  MaxSize() { return kMaxInt - 1; }
 #else
-   Ssiz_t         MaxSize() const { return (kMaxInt >> 1) - 1; }
+   static Ssiz_t  MaxSize() { return (kMaxInt >> 1) - 1; }
 #endif
    void           UnLink() const { if (IsLong()) delete [] fRep.fLong.fData; }
    void           Zero() {
diff --git a/core/base/src/Stringio.cxx b/core/base/src/Stringio.cxx
index 5cc288df92a984c4a024f0bb841f611f9c032b27..888be3d3fd68fafe0920ba494f5d9c525505c5b1 100644
--- a/core/base/src/Stringio.cxx
+++ b/core/base/src/Stringio.cxx
@@ -40,7 +40,8 @@ istream& TString::ReadFile(istream& strm)
 
    while(1) {
       Ssiz_t len = Length();
-      strm.read(GetPointer()+len, Capacity()-len);
+      Ssiz_t cap = Capacity();
+      strm.read(GetPointer()+len, cap-len);
       SetSize(len + strm.gcount());
 
       if (!strm.good())
@@ -49,7 +50,8 @@ istream& TString::ReadFile(istream& strm)
       // If we got here, the read must have stopped because
       // the buffer was going to overflow. Resize and keep
       // going.
-      Capacity(Length() + incr);
+      cap = AdjustCapacity(cap, cap+incr);
+      Capacity(cap);
    }
 
    GetPointer()[Length()] = '\0';         // Add null terminator
@@ -90,14 +92,16 @@ istream& TString::ReadToDelim(istream& strm, char delim)
    const Ssiz_t incr = 32;
    
    Clobber(incr);
+
    int p = strm.peek();             // Check if we are already at delim
    if (p == delim) {
       strm.get();                    // eat the delimiter, and return \0.
    } else {
       while (1) {
          Ssiz_t len = Length();
+         Ssiz_t cap = Capacity();
          strm.get(GetPointer()+len,          // Address of next byte
-                  Capacity()-len+1,          // Space available (+1 for terminator)
+                  cap-len+1,                 // Space available (+1 for terminator)
                   delim);                    // Delimiter
          SetSize(len + strm.gcount());
          if (!strm.good()) break;            // Check for EOF or stream failure
@@ -107,7 +111,8 @@ istream& TString::ReadToDelim(istream& strm, char delim)
             break;
          }
          // Delimiter not seen.  Resize and keep going:
-         Capacity(Length() + incr);
+         cap = AdjustCapacity(cap, cap+incr);
+         Capacity(cap);
       }
    }
 
@@ -135,9 +140,11 @@ istream& TString::ReadToken(istream& strm)
           strm.get(c).good() && (hitSpace = isspace((Int_t)c)) == 0) {
       // Check for overflow:
       Ssiz_t len = Length();
-      if (len == Capacity())
-         Capacity(len + incr);
-
+      Ssiz_t cap = Capacity();
+      if (len == cap) {
+         cap = AdjustCapacity(cap, cap+incr);
+         Capacity(cap);
+      }
       GetPointer()[len] = c;
       len++;
       SetSize(len);
diff --git a/core/base/src/TString.cxx b/core/base/src/TString.cxx
index 6a70bd1e994851b512597880f6a10ca4b7645a3e..bc71f7d39627b54cc51ed6c760f6453568b693de 100644
--- a/core/base/src/TString.cxx
+++ b/core/base/src/TString.cxx
@@ -319,7 +319,7 @@ TString& TString::Append(char c, Ssiz_t rep)
       SetSize(tot);
       data = p;
    } else {
-      Ssiz_t cap = Recommend(tot);
+      Ssiz_t cap = AdjustCapacity(capac, tot);
       data = new char[cap+1];
       memcpy(data, p, len);
       UnLink();
@@ -760,7 +760,7 @@ TString& TString::Prepend(char c, Ssiz_t rep)
       SetSize(tot);
       data = p;
    } else {
-      Ssiz_t cap = Recommend(tot);
+      Ssiz_t cap = AdjustCapacity(capac, tot);
       data = new char[cap+1];
       memcpy(data+rep, p, len);
       UnLink();
@@ -825,7 +825,7 @@ finish:
       SetSize(tot);
       p[tot] = 0;
    } else {
-      Ssiz_t cap = Recommend(tot);
+      Ssiz_t cap = AdjustCapacity(capac, tot);
       char *data = new char[cap+1];
       if (pos) memcpy(data, p, pos);
       if (n2 ) memcpy(data + pos, cs, n2);
@@ -848,8 +848,8 @@ TString& TString::ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2,
 
    if (s1 && ls1 > 0) {
       Ssiz_t index = 0;
-      while ((index = Index(s1,ls1,index, kExact)) != kNPOS) {
-         Replace(index,ls1,s2,ls2);
+      while ((index = Index(s1, ls1, index, kExact)) != kNPOS) {
+         Replace(index, ls1, s2, ls2);
          index += ls2;
       }
    }
@@ -952,11 +952,18 @@ void TString::AssertElement(Ssiz_t i) const
 }
 
 //______________________________________________________________________________
-Ssiz_t TString::AdjustCapacity(Ssiz_t nc)
+Ssiz_t TString::AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap)
 {
-   // Calculate a nice capacity greater than or equal to nc.
+   // Calculate a nice capacity greater than or equal to newCap.
 
-   return Recommend(nc);
+   Ssiz_t ms = MaxSize();
+   if (newCap > ms - 1) {
+      Error("AdjustCapacity", "capacity too large (%d, max = %d)",
+            newCap, ms);
+   }
+   Ssiz_t cap = oldCap < ms / 2 - kAlignment ?
+                Recommend(TMath::Max(newCap, 2 * oldCap)) : ms - 1;
+   return cap;
 }
 
 //______________________________________________________________________________
diff --git a/test/tstring.cxx b/test/tstring.cxx
index b25a50cfb1ffe94de6114dd7dde6cd69a7e09928..61b26e7af1277cc47dc6a4a73dfe14490febc326 100644
--- a/test/tstring.cxx
+++ b/test/tstring.cxx
@@ -7,6 +7,7 @@
 #include "TString.h"
 #include "TRegexp.h"
 #include "TPRegexp.h"
+#include "TSystem.h"
 
 
 void Ok(int i, int b)
@@ -156,6 +157,7 @@ int main()
 
    Printf("Using Print: %s (%d)\n", (const char*) s9, s9.Length());
    
+   // test comparisons
    TString s20 = "abc";
    TString s21 = "abcd";
    TString s22 = "bcde";
@@ -168,5 +170,23 @@ int main()
    Ok(31, s22.CompareTo(s23, TString::kIgnoreCase) == 0);
    Ok(32, (s23 < s24) != (s24 < s23));
 
+   // test file access
+   ifstream f("tstring.cxx");
+   f.seekg(0, ios::end);
+   Ssiz_t size = f.tellg();
+   f.seekg(0, ios::beg);
+   
+   TString fs;
+   fs.ReadFile(f);
+   Ok(33, size == fs.Length());
+
+   ifstream f2("tstring.cxx");
+   fs.ReadLine(f2);  // read '// @(#)root/test:$Id: tstring.cxx 38977..."
+   Ok(34, fs.Contains("root/test"));
+
+   fs.ReadToken(f2);   // read '//'
+   fs.ReadToken(f2);   // read 'Author:'
+   Ok(35, fs == "Author:");
+   
    return 0;
 }